Beispiel #1
0
            public override SyntaxNode VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax node)
            {
                var newNode = base.VisitSimpleLambdaExpression(node);

                if (newNode is SimpleLambdaExpressionSyntax && _expandParameter)
                {
                    var newSimpleLambda = (SimpleLambdaExpressionSyntax)newNode;
                    var parameterSymbol = _semanticModel.GetDeclaredSymbol(node.Parameter);
                    if (parameterSymbol != null && parameterSymbol.Kind == SymbolKind.Parameter)
                    {
                        if (parameterSymbol.Type != null)
                        {
                            var typeSyntax = parameterSymbol.Type.GenerateTypeSyntax().WithTrailingTrivia(s_oneWhitespaceSeparator);
                            var newSimpleLambdaParameter = newSimpleLambda.Parameter.WithType(typeSyntax).WithoutTrailingTrivia();

                            var parenthesizedLambda = SyntaxFactory.ParenthesizedLambdaExpression(
                                newSimpleLambda.AsyncKeyword,
                                SyntaxFactory.ParameterList(SyntaxFactory.SingletonSeparatedList(newSimpleLambdaParameter))
                                .WithTrailingTrivia(newSimpleLambda.Parameter.GetTrailingTrivia())
                                .WithLeadingTrivia(newSimpleLambda.Parameter.GetLeadingTrivia()),
                                newSimpleLambda.ArrowToken,
                                newSimpleLambda.Body).WithAdditionalAnnotations(Simplifier.Annotation);

                            return(SimplificationHelpers.CopyAnnotations(newNode, parenthesizedLambda));
                        }
                    }
                }

                return(newNode);
            }
        private static SyntaxNode SimplifyParenthesizedLambdaExpression(
            SyntaxNode node,
            SemanticModel semanticModel,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            if (node != null && node is ParenthesizedLambdaExpressionSyntax)
            {
                var parenthesizedLambda = (ParenthesizedLambdaExpressionSyntax)node;
                if (parenthesizedLambda.ParameterList != null &&
                    parenthesizedLambda.ParameterList.Parameters.Count == 1)
                {
                    var parameter = parenthesizedLambda.ParameterList.Parameters.First();
                    if (CanRemoveTypeFromParameter(parameter, semanticModel, cancellationToken))
                    {
                        var newParameterSyntax = parameter.WithType(null);
                        var newSimpleLambda    = SyntaxFactory.SimpleLambdaExpression(
                            parenthesizedLambda.AsyncKeyword,
                            newParameterSyntax.WithTrailingTrivia(parenthesizedLambda.ParameterList.GetTrailingTrivia()),
                            parenthesizedLambda.ArrowToken,
                            parenthesizedLambda.Body);

                        return(SimplificationHelpers.CopyAnnotations(parenthesizedLambda, newSimpleLambda).WithoutAnnotations(Simplifier.Annotation));
                    }
                }
            }

            return(node);
        }
Beispiel #3
0
        private static ExpressionSyntax SimplifyCast(CastExpressionSyntax node, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken)
        {
            if (!node.IsUnnecessaryCast(semanticModel, cancellationToken))
            {
                return(node);
            }

            var leadingTrivia = node.OpenParenToken.LeadingTrivia
                                .Concat(node.OpenParenToken.TrailingTrivia)
                                .Concat(node.Type.GetLeadingTrivia())
                                .Concat(node.Type.GetTrailingTrivia())
                                .Concat(node.CloseParenToken.LeadingTrivia)
                                .Concat(node.CloseParenToken.TrailingTrivia)
                                .Concat(node.Expression.GetLeadingTrivia())
                                .Where(t => !t.IsElastic());

            var trailingTrivia = node.GetTrailingTrivia().Where(t => !t.IsElastic());

            var resultNode = node.Expression
                             .WithLeadingTrivia(leadingTrivia)
                             .WithTrailingTrivia(trailingTrivia);

            resultNode = SimplificationHelpers.CopyAnnotations(from: node, to: resultNode);

            return(resultNode);
        }
        private static SyntaxNode SimplifyParameter(
            SyntaxNode node,
            SemanticModel semanticModel,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            if (CanRemoveTypeFromParameter(node, semanticModel, cancellationToken))
            {
                var newParameterSyntax = ((ParameterSyntax)node).WithType(null);
                newParameterSyntax = SimplificationHelpers.CopyAnnotations(node, newParameterSyntax).WithoutAnnotations(Simplifier.Annotation);
                return(newParameterSyntax);
            }

            return(node);
        }
Beispiel #5
0
        private static SyntaxNode SimplifyParentheses(
            ParenthesizedPatternSyntax node,
            SemanticModel semanticModel,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            if (node.CanRemoveParentheses(semanticModel))
            {
                var resultNode = CSharpSyntaxFacts.Instance.Unparenthesize(node);
                return(SimplificationHelpers.CopyAnnotations(from: node, to: resultNode));
            }

            // We don't know how to simplify this.
            return(node);
        }
Beispiel #6
0
        public static bool TryReduceOrSimplifyExplicitName(
            this QualifiedCrefSyntax crefSyntax,
            SemanticModel semanticModel,
            out CrefSyntax replacementNode,
            out TextSpan issueSpan,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            replacementNode = null;
            issueSpan       = default;

            var memberCref = crefSyntax.Member;

            // Currently we are dealing with only the NameMemberCrefs
            if (SimplificationHelpers.PreferPredefinedTypeKeywordInMemberAccess(optionSet, semanticModel.Language) &&
                memberCref.IsKind(SyntaxKind.NameMemberCref, out NameMemberCrefSyntax nameMemberCref))
            {
                var symbolInfo = semanticModel.GetSymbolInfo(nameMemberCref.Name, cancellationToken);
                var symbol     = symbolInfo.Symbol;

                if (symbol == null)
                {
                    return(false);
                }

                // 1. Check for Predefined Types
                if (symbol is INamedTypeSymbol namedSymbol)
                {
                    var keywordKind = ExpressionSyntaxExtensions.GetPredefinedKeywordKind(namedSymbol.SpecialType);

                    if (keywordKind != SyntaxKind.None)
                    {
                        replacementNode = CreateReplacement(crefSyntax, keywordKind);
                        replacementNode = crefSyntax.CopyAnnotationsTo(replacementNode);

                        // we want to show the whole name expression as unnecessary
                        issueSpan = crefSyntax.Span;

                        return(true);
                    }
                }
            }

            return(TryReduceOrSimplifyQualifiedCref(
                       crefSyntax, semanticModel, memberCref,
                       out replacementNode, out issueSpan, cancellationToken));
        }
Beispiel #7
0
            public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax originalNode)
            {
                var rewrittenNode = (InvocationExpressionSyntax)base.VisitInvocationExpression(originalNode);

                if (originalNode.Expression.Kind() == SyntaxKind.SimpleMemberAccessExpression)
                {
                    var memberAccess = (MemberAccessExpressionSyntax)originalNode.Expression;
                    var targetSymbol = SimplificationHelpers.GetOriginalSymbolInfo(_semanticModel, memberAccess.Name);

                    if (targetSymbol != null && targetSymbol.IsReducedExtension())
                    {
                        rewrittenNode = RewriteExtensionMethodInvocation(originalNode, rewrittenNode, ((MemberAccessExpressionSyntax)rewrittenNode.Expression).Expression, (IMethodSymbol)targetSymbol);
                    }
                }

                return(rewrittenNode);
            }
        private static SyntaxNode SimplifyParentheses(
            ParenthesizedExpressionSyntax node,
            SemanticModel semanticModel,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            if (node.CanRemoveParentheses(semanticModel))
            {
                // TODO(DustinCa): We should not be skipping elastic trivia below.
                // However, the formatter seems to mess up trailing trivia in some
                // cases if elastic trivia is there -- and it's not clear why.
                // Specifically remove the elastic trivia formatting rule doesn't
                // have any effect.
                var resultNode = CSharpSyntaxFactsService.Instance.Unparenthesize(node);
                return(SimplificationHelpers.CopyAnnotations(from: node, to: resultNode));
            }

            // We don't know how to simplify this.
            return(node);
        }
        public static ExpressionSyntax Uncast(this CastExpressionSyntax node)
        {
            var leadingTrivia = node.OpenParenToken.LeadingTrivia
                .Concat(node.OpenParenToken.TrailingTrivia)
                .Concat(node.Type.GetLeadingTrivia())
                .Concat(node.Type.GetTrailingTrivia())
                .Concat(node.CloseParenToken.LeadingTrivia)
                .Concat(node.CloseParenToken.TrailingTrivia)
                .Concat(node.Expression.GetLeadingTrivia())
                .Where(t => !t.IsElastic());

            var trailingTrivia = node.GetTrailingTrivia().Where(t => !t.IsElastic());

            var resultNode = node.Expression
                .WithLeadingTrivia(leadingTrivia)
                .WithTrailingTrivia(trailingTrivia)
                .WithAdditionalAnnotations(Simplifier.Annotation);

            resultNode = SimplificationHelpers.CopyAnnotations(from: node, to: resultNode);

            return resultNode;
        }
        private static bool IsThisOrTypeOrNamespace(MemberAccessExpressionSyntax memberAccess, SemanticModel semanticModel)
        {
            if (memberAccess.Expression.Kind() == SyntaxKind.ThisExpression)
            {
                var previousToken = memberAccess.Expression.GetFirstToken().GetPreviousToken();

                var symbol = semanticModel.GetSymbolInfo(memberAccess.Name).Symbol;

                if (previousToken.Kind() == SyntaxKind.OpenParenToken &&
                    previousToken.Parent.IsKind(SyntaxKind.ParenthesizedExpression, out ParenthesizedExpressionSyntax parenExpr) &&
                    !parenExpr.IsParentKind(SyntaxKind.ParenthesizedExpression) &&
                    parenExpr.Expression.Kind() == SyntaxKind.SimpleMemberAccessExpression &&
                    symbol != null && symbol.Kind == SymbolKind.Method)
                {
                    return(false);
                }

                return(true);
            }

            var expressionInfo = semanticModel.GetSymbolInfo(memberAccess.Expression);

            if (SimplificationHelpers.IsValidSymbolInfo(expressionInfo.Symbol))
            {
                if (expressionInfo.Symbol is INamespaceOrTypeSymbol)
                {
                    return(true);
                }

                if (expressionInfo.Symbol.IsThisParameter())
                {
                    return(true);
                }
            }

            return(false);
        }
        private static SyntaxNode SimplifyParentheses(
            ParenthesizedExpressionSyntax node,
            SemanticModel semanticModel,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            if (node.CanRemoveParentheses(semanticModel))
            {
                // TODO(DustinCa): We should not be skipping elastic trivia below.
                // However, the formatter seems to mess up trailing trivia in some
                // cases if elastic trivia is there -- and it's not clear why.
                // Specifically remove the elastic trivia formatting rule doesn't
                // have any effect.

                var leadingTrivia = node.OpenParenToken.LeadingTrivia
                                    .Concat(node.OpenParenToken.TrailingTrivia)
                                    .Where(t => !t.IsElastic())
                                    .Concat(node.Expression.GetLeadingTrivia());

                var trailingTrivia = node.Expression.GetTrailingTrivia()
                                     .Concat(node.CloseParenToken.LeadingTrivia)
                                     .Where(t => !t.IsElastic())
                                     .Concat(node.CloseParenToken.TrailingTrivia);

                var resultNode = node.Expression
                                 .WithLeadingTrivia(leadingTrivia)
                                 .WithTrailingTrivia(trailingTrivia);

                resultNode = SimplificationHelpers.CopyAnnotations(from: node, to: resultNode);

                return(resultNode);
            }

            // We don't know how to simplify this.
            return(node);
        }
Beispiel #12
0
        static bool GenerateMeshData(IvyGraph ivyGraph, IvyProfile ivyProfile, bool forceGeneration = false)
        {
            var p = ivyProfile;

            //branches
            foreach (var root in ivyGraph.roots)
            {
                var cache = IvyRoot.GetMeshCacheFor(root);
                if (root.useCachedBranchData && !forceGeneration)
                {
                    combinedTriangleIndices.Clear();
                    cache.triangles.ForEach(localIndex => combinedTriangleIndices.Add(localIndex + verticesAll.Count));
                    trianglesAll.AddRange(combinedTriangleIndices);

                    verticesAll.AddRange(cache.vertices);
                    texCoordsAll.AddRange(cache.texCoords);
                    continue;
                }
                root.useCachedBranchData = true;

                //process only roots with more than one node
                if (root.nodes.Count < 2)
                {
                    continue;
                }

                cache.vertices.Clear();
                cache.texCoords.Clear();
                cache.triangles.Clear();

                //branch diameter depends on number of parents AND branch taper
                float local_ivyBranchDiameter = 1.0f / Mathf.Lerp(1f, 1f + root.parents, ivyProfile.branchTaper);

                // smooth the line... which increases points a lot
                allPoints = root.nodes.Select(node => node.p).ToList();
                var useThesePoints = allPoints;
                if (ivyProfile.branchSmooth > 1)
                {
                    SmoothLineCatmullRomNonAlloc(allPoints, smoothPoints, ivyProfile.branchSmooth);
                    useThesePoints = smoothPoints;
                }

                // generate simplified points for each root, to make it less wavy AND save tris
                if (!root.isAlive && ivyProfile.branchOptimize > 0f)
                {
                    newPoints.Clear();
                    newPoints.AddRange(SimplificationHelpers.Simplify <Vector3>(
                                           useThesePoints,
                                           (vec1, vec2) => vec1 == vec2,
                                           (vec) => vec.x,
                                           (vec) => vec.y,
                                           (vec) => vec.z,
                                           ivyProfile.branchOptimize * ivyProfile.ivyStepDistance * 0.5f,
                                           false
                                           ));
                    useThesePoints = newPoints;
                }

                // I'm not sure why there's this bug when we use Catmull Rom + line simplify, but let's do this hacky fix
                // if ( ivyProfile.branchSmooth > 1 && ivyProfile.branchOptimize > 0f ) {
                //     useThesePoints.ForEach( delegate(Vector3 point) {
                //         if ( float.IsInfinity(point.x) ) {point.x = 0f;}
                //         if ( float.IsInfinity(point.y) ) {point.y = 0f;}
                //         if ( float.IsInfinity(point.z) ) {point.z = 0f;}
                //     } );
                // }

                for (int n = 0; n < useThesePoints.Count; n++)
                {
                    if (verticesAll.Count >= 65531)
                    {
                        Debug.LogWarning("Hedera: ending branch generation early, reached ~65536 vertex limit on mesh " + ivyGraph.seedPos + "... but this could technically be solved in Unity 2017.3+ or later with 32-bit index formats for meshes? The exercise is left to the reader.");
                        break;
                    }
                    cache.meshSegments = n + 1;

                    //weight depending on ratio of node length to total length
                    float taper = 1f * n / useThesePoints.Count;
                    taper = Mathf.Lerp(1f, (1f - taper) * taper, ivyProfile.branchTaper);

                    //create trihedral vertices... TODO: let user specify how many sides?
                    Vector3 up    = Vector3.down;
                    Vector3 basis = Vector3.Normalize(n < useThesePoints.Count - 1 ? useThesePoints[n + 1] - useThesePoints[n] : -(useThesePoints[n] - useThesePoints[n - 1]));
                    // Debug.DrawLine( newPoints[node+1] + ivyGraph.seedPos, newPoints[node] + ivyGraph.seedPos, Color.cyan, 5f, false);

                    int   edges = 3;                        // TODO: finish this, make it configurable
                    float texV  = (n % 2 == 0 ? 1f : 0.0f); // vertical UV tiling
                    for (int b = 0; b < edges; b++)
                    {
                        // generate vertices
                        if (b == 0)
                        {
                            branchVertBasis[b] = Vector3.Cross(up, basis).normalized *Mathf.Max(0.001f, local_ivyBranchDiameter * p.ivyBranchSize * taper) + useThesePoints[n];
                        }
                        else
                        {
                            branchVertBasis[b] = RotateAroundAxis(branchVertBasis[0], useThesePoints[n], basis, 6.283f * b / edges);
                        }
                        cache.vertices.Add(branchVertBasis[b]);

                        // generate UVs
                        cache.texCoords.Add(new Vector2(1f * b / (edges - 1), texV));

                        // add triangles
                        // AddTriangle(root, 4, 1, 5);
                        // AddTriangle(root, 5, 1, 2);

                        // TODO: finish this
                    }

                    if (n == 0)   // start cap
                    {
                        if (taper > 0f)
                        {
                            AddTriangle(cache, 1, 2, 3);
                        }
                        continue;
                    }

                    AddTriangle(cache, 4, 1, 5);
                    AddTriangle(cache, 5, 1, 2);

                    AddTriangle(cache, 5, 2, 6);
                    AddTriangle(cache, 6, 2, 3);

                    AddTriangle(cache, 6, 3, 1);
                    AddTriangle(cache, 6, 1, 4);

                    if (n == useThesePoints.Count - 1 && taper > 0f) // end cap
                    {
                        AddTriangle(cache, 3, 2, 1);
                    }
                }

                combinedTriangleIndices.Clear();
                cache.triangles.ForEach(localIndex => combinedTriangleIndices.Add(localIndex + verticesAll.Count));
                trianglesAll.AddRange(combinedTriangleIndices);

                verticesAll.AddRange(cache.vertices);
                texCoordsAll.AddRange(cache.texCoords);
            }

            if (ivyProfile.ivyLeafSize <= 0.001f || ivyProfile.leafProbability <= 0.001f)
            {
                return(true);
            }

            //create leafs
            allLeafPoints.Clear();
            foreach (var root in ivyGraph.roots)
            {
                // don't bother on small roots
                if (root.nodes.Count <= 2)
                {
                    root.useCachedLeafData = false;
                    continue;
                }
                var cache = IvyRoot.GetMeshCacheFor(root);

                // use cached mesh data for leaves only if (a) we're supposed to, and (b) if not using vertex colors OR vertex colors seem valid
                if (root.useCachedLeafData && !forceGeneration && (!ivyProfile.useVertexColors || cache.leafVertices.Count == cache.leafVertexColors.Count))
                {
                    combinedTriangleIndices.Clear();
                    cache.leafTriangles.ForEach(index => combinedTriangleIndices.Add(index + leafVerticesAll.Count));
                    leafTrianglesAll.AddRange(combinedTriangleIndices);

                    allLeafPoints.AddRange(cache.leafPoints);
                    leafVerticesAll.AddRange(cache.leafVertices);
                    leafUVsAll.AddRange(cache.leafUVs);
                    if (ivyProfile.useVertexColors)
                    {
                        leafColorsAll.AddRange(cache.leafVertexColors);
                    }
                    continue;
                }
                root.useCachedLeafData = true;
                cache.leafPoints.Clear();
                cache.leafVertices.Clear();
                cache.leafUVs.Clear();
                cache.leafTriangles.Clear();
                cache.leafVertexColors.Clear();

                // simple multiplier, just to make it a more dense
                for (int i = 0; i < 1; ++i)
                {
                    var leafPositions = GetAllSamplePosAlongRoot(root, p.ivyLeafSize);

                    // for(int n=0; n<root.nodes.Count; n++)
                    foreach (var kvp in leafPositions)
                    {
                        if (leafVerticesAll.Count >= 65530)
                        {
                            Debug.LogWarning("Hedera: ending leaf generation early, reached ~65536 vertex limit on mesh " + ivyGraph.seedPos + "... but this could technically be solved in Unity 2017.3+ or later with 32-bit index formats for meshes? The exercise is left to the reader.");
                            break;
                        }

                        int     n          = kvp.Value;
                        Vector3 newLeafPos = kvp.Key;
                        var     node       = root.nodes[n];

                        // // do not generate a leaf on the first few nodes
                        // if ( n <= 1 ) { // || n >= root.nodes.Count
                        //     continue;
                        // }

                        // probability of leaves on the ground is increased
                        float groundedness = Vector3.Dot(Vector3.down, node.c.normalized);
                        if (groundedness < -0.02f)
                        {
                            groundedness -= 0.1f;
                            groundedness *= 3f;
                        }
                        else
                        {
                            groundedness = (groundedness - 0.25f) * 0.5f;
                        }
                        groundedness *= ivyProfile.leafSunlightBonus * p.leafProbability;

                        // don't spawn a leaf on top of another leaf
                        bool  badLeafPos  = false;
                        float leafSqrSize = p.ivyLeafSize * p.ivyLeafSize * Mathf.Clamp(1f - p.leafProbability - groundedness, 0.01f, 2f);
                        for (int f = 0; f < allLeafPoints.Count; f++)
                        {
                            if (Vector3.SqrMagnitude(allLeafPoints[f] - newLeafPos) < leafSqrSize)
                            {
                                badLeafPos = true;
                                break;
                            }
                        }
                        if (badLeafPos)
                        {
                            continue;
                        }

                        IvyNode previousNode     = root.nodes[Mathf.Max(0, n - 1)];
                        float   randomSpreadHack = 0.25f;
                        if (n <= 1 || n == root.nodes.Count - 1)
                        {
                            randomSpreadHack = 0f;
                        }

                        // randomize leaf probability // guarantee a leaf on the first or last node
                        if ((Random.value + groundedness > 1f - p.leafProbability) || randomSpreadHack == 0f)
                        {
                            cache.leafPoints.Add(node.p);
                            allLeafPoints.Add(node.p);

                            //center of leaf quad
                            Vector3 up     = (newLeafPos - previousNode.p).normalized;
                            Vector3 right  = Vector3.Cross(up, node.c);
                            Vector3 center = newLeafPos - node.c.normalized * 0.05f + (up * Random.Range(-1f, 1f) + right * Random.Range(-1f, 1f)) * randomSpreadHack * p.ivyLeafSize;

                            //size of leaf
                            float sizeWeight = 1.5f - (Mathf.Abs(Mathf.Cos(2.0f * Mathf.PI)) * 0.5f + 0.5f);
                            float leafSize   = p.ivyLeafSize * sizeWeight + Random.Range(-p.ivyLeafSize, p.ivyLeafSize) * 0.1f + (p.ivyLeafSize * groundedness);
                            leafSize = Mathf.Max(0.01f, leafSize);

                            Quaternion facing = node.c.sqrMagnitude < 0.001f ? Quaternion.identity : Quaternion.LookRotation(Vector3.Lerp(-node.c, Vector3.up, Mathf.Clamp01(0.68f - Mathf.Abs(groundedness)) * ivyProfile.leafSunlightBonus), Random.onUnitSphere);
                            AddLeafVertex(cache, center, new Vector3(-1f, 1f, 0f), leafSize, facing);
                            AddLeafVertex(cache, center, new Vector3(1f, 1f, 0f), leafSize, facing);
                            AddLeafVertex(cache, center, new Vector3(-1f, -1f, 0f), leafSize, facing);
                            AddLeafVertex(cache, center, new Vector3(1f, -1f, 0f), leafSize, facing);

                            cache.leafUVs.Add(new Vector2(1.0f, 1.0f));
                            cache.leafUVs.Add(new Vector2(0.0f, 1.0f));
                            cache.leafUVs.Add(new Vector2(1.0f, 0.0f));
                            cache.leafUVs.Add(new Vector2(0.0f, 0.0f));

                            if (ivyProfile.useVertexColors)
                            {
                                var randomColor = ivyProfile.leafVertexColors.Evaluate(Random.value);
                                cache.leafVertexColors.Add(randomColor);
                                cache.leafVertexColors.Add(randomColor);
                                cache.leafVertexColors.Add(randomColor);
                                cache.leafVertexColors.Add(randomColor);
                            }

                            // calculate normal of the leaf tri, and make it face outwards
                            // var normal = GetNormal(
                            //     ivyGraph.leafVertices[ivyGraph.leafVertices.Count - 2],
                            //     ivyGraph.leafVertices[ivyGraph.leafVertices.Count - 4],
                            //     ivyGraph.leafVertices[ivyGraph.leafVertices.Count - 3]
                            // );
                            // if ( Vector3.Dot( normal, node.adhesionVector) < 0f) {
                            //    AddLeafTriangle(ivyGraph, 2, 4, 3);
                            //    AddLeafTriangle(ivyGraph, 3, 1, 2);
                            // } else {
                            AddLeafTriangle(cache, 1, 3, 4);
                            AddLeafTriangle(cache, 4, 2, 1);
                            // }
                        }
                    }
                    combinedTriangleIndices.Clear();
                    cache.leafTriangles.ForEach(index => combinedTriangleIndices.Add(index + leafVerticesAll.Count));
                    leafTrianglesAll.AddRange(combinedTriangleIndices);

                    leafVerticesAll.AddRange(cache.leafVertices);
                    leafUVsAll.AddRange(cache.leafUVs);
                    if (ivyProfile.useVertexColors)
                    {
                        leafColorsAll.AddRange(cache.leafVertexColors);
                    }
                }
            }
            return(true);
        }
Beispiel #13
0
        public override bool TrySimplify(
            NameSyntax name,
            SemanticModel semanticModel,
            OptionSet optionSet,
            out TypeSyntax replacementNode,
            out TextSpan issueSpan,
            CancellationToken cancellationToken)
        {
            replacementNode = null;
            issueSpan       = default;

            if (name.IsVar)
            {
                return(false);
            }

            // we should not simplify a name of a namespace declaration
            if (IsPartOfNamespaceDeclarationName(name))
            {
                return(false);
            }

            // We can simplify Qualified names and AliasQualifiedNames. Generally, if we have
            // something like "A.B.C.D", we only consider the full thing something we can simplify.
            // However, in the case of "A.B.C<>.D", then we'll only consider simplifying up to the
            // first open name.  This is because if we remove the open name, we'll often change
            // meaning as "D" will bind to C<T>.D which is different than C<>.D!
            if (name is QualifiedNameSyntax qualifiedName)
            {
                var left = qualifiedName.Left;
                if (ContainsOpenName(left))
                {
                    // Don't simplify A.B<>.C
                    return(false);
                }
            }

            // 1. see whether binding the name binds to a symbol/type. if not, it is ambiguous and
            //    nothing we can do here.
            var symbol = SimplificationHelpers.GetOriginalSymbolInfo(semanticModel, name);

            if (symbol == null)
            {
                return(false);
            }

            // treat constructor names as types
            var method = symbol as IMethodSymbol;

            if (method.IsConstructor())
            {
                symbol = method.ContainingType;
            }

            if (symbol.Kind == SymbolKind.Method && name.Kind() == SyntaxKind.GenericName)
            {
                var genericName = (GenericNameSyntax)name;
                replacementNode = SyntaxFactory.IdentifierName(genericName.Identifier)
                                  .WithLeadingTrivia(genericName.GetLeadingTrivia())
                                  .WithTrailingTrivia(genericName.GetTrailingTrivia());

                issueSpan = genericName.TypeArgumentList.Span;
                return(CanReplaceWithReducedName(
                           name, replacementNode, semanticModel, cancellationToken));
            }

            if (!(symbol is INamespaceOrTypeSymbol))
            {
                return(false);
            }

            if (name.HasAnnotations(SpecialTypeAnnotation.Kind))
            {
                replacementNode = SyntaxFactory.PredefinedType(
                    SyntaxFactory.Token(
                        name.GetLeadingTrivia(),
                        GetPredefinedKeywordKind(SpecialTypeAnnotation.GetSpecialType(name.GetAnnotations(SpecialTypeAnnotation.Kind).First())),
                        name.GetTrailingTrivia()));

                issueSpan = name.Span;

                return(CanReplaceWithReducedNameInContext(name, replacementNode, semanticModel));
            }
            else
            {
                if (!name.IsRightSideOfDotOrColonColon())
                {
                    if (TryReplaceExpressionWithAlias(name, semanticModel, symbol, cancellationToken, out var aliasReplacement))
                    {
                        // get the token text as it appears in source code to preserve e.g. Unicode character escaping
                        var text      = aliasReplacement.Name;
                        var syntaxRef = aliasReplacement.DeclaringSyntaxReferences.FirstOrDefault();

                        if (syntaxRef != null)
                        {
                            var declIdentifier = ((UsingDirectiveSyntax)syntaxRef.GetSyntax(cancellationToken)).Alias.Name.Identifier;
                            text = declIdentifier.IsVerbatimIdentifier() ? declIdentifier.ToString().Substring(1) : declIdentifier.ToString();
                        }

                        var identifierToken = SyntaxFactory.Identifier(
                            name.GetLeadingTrivia(),
                            SyntaxKind.IdentifierToken,
                            text,
                            aliasReplacement.Name,
                            name.GetTrailingTrivia());

                        identifierToken = CSharpSimplificationService.TryEscapeIdentifierToken(identifierToken, name);
                        replacementNode = SyntaxFactory.IdentifierName(identifierToken);

                        // Merge annotation to new syntax node
                        var annotatedNodesOrTokens = name.GetAnnotatedNodesAndTokens(RenameAnnotation.Kind);
                        foreach (var annotatedNodeOrToken in annotatedNodesOrTokens)
                        {
                            if (annotatedNodeOrToken.IsToken)
                            {
                                identifierToken = annotatedNodeOrToken.AsToken().CopyAnnotationsTo(identifierToken);
                            }
                            else
                            {
                                replacementNode = annotatedNodeOrToken.AsNode().CopyAnnotationsTo(replacementNode);
                            }
                        }

                        annotatedNodesOrTokens = name.GetAnnotatedNodesAndTokens(AliasAnnotation.Kind);
                        foreach (var annotatedNodeOrToken in annotatedNodesOrTokens)
                        {
                            if (annotatedNodeOrToken.IsToken)
                            {
                                identifierToken = annotatedNodeOrToken.AsToken().CopyAnnotationsTo(identifierToken);
                            }
                            else
                            {
                                replacementNode = annotatedNodeOrToken.AsNode().CopyAnnotationsTo(replacementNode);
                            }
                        }

                        replacementNode = ((SimpleNameSyntax)replacementNode).WithIdentifier(identifierToken);
                        issueSpan       = name.Span;

                        // In case the alias name is the same as the last name of the alias target, we only include
                        // the left part of the name in the unnecessary span to Not confuse uses.
                        if (name.Kind() == SyntaxKind.QualifiedName)
                        {
                            var qualifiedName3 = (QualifiedNameSyntax)name;

                            if (qualifiedName3.Right.Identifier.ValueText == identifierToken.ValueText)
                            {
                                issueSpan = qualifiedName3.Left.Span;
                            }
                        }

                        // first check if this would be a valid reduction
                        if (CanReplaceWithReducedNameInContext(name, replacementNode, semanticModel))
                        {
                            // in case this alias name ends with "Attribute", we're going to see if we can also
                            // remove that suffix.
                            if (TryReduceAttributeSuffix(
                                    name,
                                    identifierToken,
                                    out var replacementNodeWithoutAttributeSuffix,
                                    out var issueSpanWithoutAttributeSuffix))
                            {
                                if (CanReplaceWithReducedName(name, replacementNodeWithoutAttributeSuffix, semanticModel, cancellationToken))
                                {
                                    replacementNode = replacementNode.CopyAnnotationsTo(replacementNodeWithoutAttributeSuffix);
                                    issueSpan       = issueSpanWithoutAttributeSuffix;
                                }
                            }

                            return(true);
                        }

                        return(false);
                    }

                    var nameHasNoAlias = false;

                    if (name is SimpleNameSyntax simpleName)
                    {
                        if (!simpleName.Identifier.HasAnnotations(AliasAnnotation.Kind))
                        {
                            nameHasNoAlias = true;
                        }
                    }

                    if (name is QualifiedNameSyntax qualifiedName2)
                    {
                        if (!qualifiedName2.Right.HasAnnotation(Simplifier.SpecialTypeAnnotation))
                        {
                            nameHasNoAlias = true;
                        }
                    }

                    if (name is AliasQualifiedNameSyntax aliasQualifiedName)
                    {
                        if (aliasQualifiedName.Name is SimpleNameSyntax &&
                            !aliasQualifiedName.Name.Identifier.HasAnnotations(AliasAnnotation.Kind) &&
                            !aliasQualifiedName.Name.HasAnnotation(Simplifier.SpecialTypeAnnotation))
                        {
                            nameHasNoAlias = true;
                        }
                    }

                    var aliasInfo = semanticModel.GetAliasInfo(name, cancellationToken);
                    if (nameHasNoAlias && aliasInfo == null)
                    {
                        // Don't simplify to predefined type if name is part of a QualifiedName.
                        // QualifiedNames can't contain PredefinedTypeNames (although MemberAccessExpressions can).
                        // In other words, the left side of a QualifiedName can't be a PredefinedTypeName.
                        var inDeclarationContext  = PreferPredefinedTypeKeywordInDeclarations(name, optionSet, semanticModel);
                        var inMemberAccessContext = PreferPredefinedTypeKeywordInMemberAccess(name, optionSet, semanticModel);

                        if (!name.Parent.IsKind(SyntaxKind.QualifiedName) && (inDeclarationContext || inMemberAccessContext))
                        {
                            // See if we can simplify this name (like System.Int32) to a built-in type (like 'int').
                            // If not, we'll still fall through and see if we can convert it to Int32.

                            var codeStyleOptionName = inDeclarationContext
                                ? nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration)
                                : nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess);

                            var type = semanticModel.GetTypeInfo(name, cancellationToken).Type;
                            if (type != null)
                            {
                                var keywordKind = GetPredefinedKeywordKind(type.SpecialType);
                                if (keywordKind != SyntaxKind.None &&
                                    CanReplaceWithPredefinedTypeKeywordInContext(name, semanticModel, out replacementNode, ref issueSpan, keywordKind, codeStyleOptionName))
                                {
                                    return(true);
                                }
                            }
                            else
                            {
                                var typeSymbol = semanticModel.GetSymbolInfo(name, cancellationToken).Symbol;
                                if (typeSymbol.IsKind(SymbolKind.NamedType))
                                {
                                    var keywordKind = GetPredefinedKeywordKind(((INamedTypeSymbol)typeSymbol).SpecialType);
                                    if (keywordKind != SyntaxKind.None &&
                                        CanReplaceWithPredefinedTypeKeywordInContext(name, semanticModel, out replacementNode, ref issueSpan, keywordKind, codeStyleOptionName))
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }
                    }

                    // Nullable rewrite: Nullable<int> -> int?
                    // Don't rewrite in the case where Nullable<int> is part of some qualified name like Nullable<int>.Something
                    if (!name.IsVar && symbol.Kind == SymbolKind.NamedType && !name.IsLeftSideOfQualifiedName())
                    {
                        var type = (INamedTypeSymbol)symbol;
                        if (aliasInfo == null && CanSimplifyNullable(type, name, semanticModel))
                        {
                            GenericNameSyntax genericName;
                            if (name.Kind() == SyntaxKind.QualifiedName)
                            {
                                genericName = (GenericNameSyntax)((QualifiedNameSyntax)name).Right;
                            }
                            else
                            {
                                genericName = (GenericNameSyntax)name;
                            }

                            var oldType = genericName.TypeArgumentList.Arguments.First();
                            if (oldType.Kind() == SyntaxKind.OmittedTypeArgument)
                            {
                                return(false);
                            }

                            replacementNode = SyntaxFactory.NullableType(oldType)
                                              .WithLeadingTrivia(name.GetLeadingTrivia())
                                              .WithTrailingTrivia(name.GetTrailingTrivia());
                            issueSpan = name.Span;

                            // we need to simplify the whole qualified name at once, because replacing the identifier on the left in
                            // System.Nullable<int> alone would be illegal.
                            // If this fails we want to continue to try at least to remove the System if possible.
                            if (CanReplaceWithReducedNameInContext(name, replacementNode, semanticModel))
                            {
                                return(true);
                            }
                        }
                    }
                }

                SyntaxToken identifier;
                switch (name.Kind())
                {
                case SyntaxKind.AliasQualifiedName:
                    var simpleName = ((AliasQualifiedNameSyntax)name).Name
                                     .WithLeadingTrivia(name.GetLeadingTrivia());

                    simpleName = simpleName.ReplaceToken(simpleName.Identifier,
                                                         ((AliasQualifiedNameSyntax)name).Name.Identifier.CopyAnnotationsTo(
                                                             simpleName.Identifier.WithLeadingTrivia(
                                                                 ((AliasQualifiedNameSyntax)name).Alias.Identifier.LeadingTrivia)));

                    replacementNode = simpleName;

                    issueSpan = ((AliasQualifiedNameSyntax)name).Alias.Span;

                    break;

                case SyntaxKind.QualifiedName:
                    replacementNode = ((QualifiedNameSyntax)name).Right.WithLeadingTrivia(name.GetLeadingTrivia());
                    issueSpan       = ((QualifiedNameSyntax)name).Left.Span;

                    break;

                case SyntaxKind.IdentifierName:
                    identifier = ((IdentifierNameSyntax)name).Identifier;

                    // we can try to remove the Attribute suffix if this is the attribute name
                    TryReduceAttributeSuffix(name, identifier, out replacementNode, out issueSpan);
                    break;
                }
            }

            if (replacementNode == null)
            {
                return(false);
            }

            // We may be looking at a name `X.Y` seeing if we can replace it with `Y`.  However, in
            // order to know for sure, we actually have to look slightly higher at `X.Y.Z` to see if
            // it can simplify to `Y.Z`.  This is because in the `Color Color` case we can only tell
            // if we can reduce by looking by also looking at what comes next to see if it will
            // cause the simplified name to bind to the instance or static side.
            if (TryReduceCrefColorColor(name, replacementNode, semanticModel, cancellationToken))
            {
                return(true);
            }

            return(CanReplaceWithReducedName(name, replacementNode, semanticModel, cancellationToken));
        }
Beispiel #14
0
 private void pb_Draw_MouseUp(object sender, MouseEventArgs e)
 {
     isMouseDown = false;
     if (drawCheckbox.Checked)
     {
         try
         {
             IList <Point> simplifiedPointsLine = SimplificationHelpers.Simplify <Point>(
                 pointCollection,
                 (p1, p2) => p1 == p2,
                 (p) => p.X,
                 (p) => p.Y,
                 Convert.ToDouble(tolerance_textbox.Text),
                 hq_checkbox.Checked
                 );
             pointCollection        = new List <Point>();
             outputPointsLabel.Text = "Output points: " + simplifiedPointsLine.Count;
             if (tb_width.Text != "" && lv_charmap.SelectedItems.Count != 0)
             {
                 if (autoInputOutputPoints.Checked && simplifiedPointsLine.Count > 0) //if checked - adding input point as input point
                 {
                     lv_points.Items.Add(simplifiedPointsLine[0].X / 2 + "," + simplifiedPointsLine[0].Y / 2 + ",-1,-1");
                     segs++;
                 }
                 for (int i = 0; i < simplifiedPointsLine.Count - 1; i++) //iterating through every point except the last one because line builds of two points - this and next
                 {
                     lv_points.Items.Add(simplifiedPointsLine[i].X / 2 + "," + simplifiedPointsLine[i].Y / 2 + "," + (simplifiedPointsLine[i + 1].X / 2 + "," + simplifiedPointsLine[i + 1].Y / 2));
                     segs++;
                 }
                 selected_seg = segs - 1;
                 for (int i = 0; i < segs; i++)
                 {
                     lv_points.Items[i].Selected = false;
                     lv_points.Items[i].Focused  = false;
                 }
                 lv_points.Items[segs - 1].Selected = true;
                 lv_points.Items[segs - 1].Focused  = true;
                 if (autoInputOutputPoints.Checked && simplifiedPointsLine.Count > 0) //if checked - adding last point as output point
                 {
                     lv_points.Items.Add("-1,-1," + simplifiedPointsLine[simplifiedPointsLine.Count - 1].X / 2 + "," + simplifiedPointsLine[simplifiedPointsLine.Count - 1].Y / 2);
                     segs++;
                 }
                 if (autogapCheckbox.Checked) //autogapping on fly
                 {
                     remove_gaps(null, null); //it removes gapps and saves the array
                 }
                 else
                 {
                     setButton_Click(null, null); //it saves the array
                 }
             }
             else
             {
                 MaterialMessageBox.Show("Select the char and enter the width first!");
             }
         }
         catch (FormatException exep)
         {
             MaterialMessageBox.Show("Tolerance value is incorrect!");
         }
         //simplifying the pointcollection
     }
 }
Beispiel #15
0
        public static bool TryReduceOrSimplifyExplicitName(
            this CrefSyntax crefSyntax,
            SemanticModel semanticModel,
            out CrefSyntax replacementNode,
            out TextSpan issueSpan,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            replacementNode = null;
            issueSpan       = default;

            // Currently Qualified Cref is the only CrefSyntax We are handling separately
            if (crefSyntax.Kind() != SyntaxKind.QualifiedCref)
            {
                return(false);
            }

            var qualifiedCrefSyntax = (QualifiedCrefSyntax)crefSyntax;
            var memberCref          = qualifiedCrefSyntax.Member;

            // Currently we are dealing with only the NameMemberCrefs
            if (SimplificationHelpers.PreferPredefinedTypeKeywordInMemberAccess(optionSet, semanticModel.Language) &&
                (memberCref.Kind() == SyntaxKind.NameMemberCref))
            {
                var nameMemberCref = ((NameMemberCrefSyntax)memberCref).Name;
                var symbolInfo     = semanticModel.GetSymbolInfo(nameMemberCref, cancellationToken);
                var symbol         = symbolInfo.Symbol;

                if (symbol == null)
                {
                    return(false);
                }

                if (symbol is INamespaceOrTypeSymbol namespaceOrTypeSymbol)
                {
                    // 1. Check for Predefined Types
                    if (symbol is INamedTypeSymbol namedSymbol)
                    {
                        var keywordKind = ExpressionSyntaxExtensions.GetPredefinedKeywordKind(namedSymbol.SpecialType);

                        if (keywordKind != SyntaxKind.None)
                        {
                            replacementNode = SyntaxFactory.TypeCref(
                                SyntaxFactory.PredefinedType(
                                    SyntaxFactory.Token(crefSyntax.GetLeadingTrivia(), keywordKind, crefSyntax.GetTrailingTrivia())));
                            replacementNode = crefSyntax.CopyAnnotationsTo(replacementNode);

                            // we want to show the whole name expression as unnecessary
                            issueSpan = crefSyntax.Span;

                            return(true);
                        }
                    }
                }
            }

            var oldSymbol = semanticModel.GetSymbolInfo(crefSyntax, cancellationToken).Symbol;

            if (oldSymbol != null)
            {
                var speculativeBindingOption = SpeculativeBindingOption.BindAsExpression;
                if (oldSymbol is INamespaceOrTypeSymbol)
                {
                    speculativeBindingOption = SpeculativeBindingOption.BindAsTypeOrNamespace;
                }

                var newSymbol = semanticModel.GetSpeculativeSymbolInfo(crefSyntax.SpanStart, memberCref, speculativeBindingOption).Symbol;

                if (newSymbol == oldSymbol)
                {
                    // Copy Trivia and Annotations
                    memberCref      = memberCref.WithLeadingTrivia(crefSyntax.GetLeadingTrivia());
                    memberCref      = crefSyntax.CopyAnnotationsTo(memberCref);
                    issueSpan       = qualifiedCrefSyntax.Container.Span;
                    replacementNode = memberCref;
                    return(true);
                }
            }

            return(false);
        }
        // Note: The caller needs to verify that replacement doesn't change semantics of the original expression.
        private static bool TrySimplifyMemberAccessOrQualifiedName(
            ExpressionSyntax left,
            ExpressionSyntax right,
            SemanticModel semanticModel,
            out ExpressionSyntax replacementNode,
            out TextSpan issueSpan)
        {
            replacementNode = null;
            issueSpan = default;

            if (left != null && right != null)
            {
                var leftSymbol = SimplificationHelpers.GetOriginalSymbolInfo(semanticModel, left);
                if (leftSymbol != null && leftSymbol.Kind == SymbolKind.NamedType)
                {
                    var rightSymbol = SimplificationHelpers.GetOriginalSymbolInfo(semanticModel, right);
                    if (rightSymbol != null && (rightSymbol.IsStatic || rightSymbol.Kind == SymbolKind.NamedType))
                    {
                        // Static member access or nested type member access.
                        var containingType = rightSymbol.ContainingType;

                        var enclosingSymbol = semanticModel.GetEnclosingSymbol(left.SpanStart);
                        var enclosingTypeParametersInsideOut = new List<ISymbol>();

                        while (enclosingSymbol != null)
                        {
                            if (enclosingSymbol is IMethodSymbol methodSymbol)
                            {
                                if (methodSymbol.TypeArguments.Length != 0)
                                {
                                    enclosingTypeParametersInsideOut.AddRange(methodSymbol.TypeArguments);
                                }
                            }

                            if (enclosingSymbol is INamedTypeSymbol namedTypeSymbol)
                            {
                                if (namedTypeSymbol.TypeArguments.Length != 0)
                                {
                                    enclosingTypeParametersInsideOut.AddRange(namedTypeSymbol.TypeArguments);
                                }
                            }

                            enclosingSymbol = enclosingSymbol.ContainingSymbol;
                        }

                        if (containingType != null && !containingType.Equals(leftSymbol))
                        {
                            if (leftSymbol is INamedTypeSymbol namedType &&
                                containingType.TypeArguments.Length != 0)
                            {
                                return false;
                            }

                            // We have a static member access or a nested type member access using a more derived type.
                            // Simplify syntax so as to use accessed member's most immediate containing type instead of the derived type.
                            replacementNode = containingType.GenerateTypeSyntax()
                                .WithLeadingTrivia(left.GetLeadingTrivia())
                                .WithTrailingTrivia(left.GetTrailingTrivia());
                            issueSpan = left.Span;
                            return true;
                        }
                    }
                }
            }

            return false;
        }
        private static bool TryReduceMemberAccessExpression(
            MemberAccessExpressionSyntax memberAccess,
            SemanticModel semanticModel,
            out TypeSyntax replacementNode,
            out TextSpan issueSpan,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            replacementNode = null;
            issueSpan = default;

            if (memberAccess.Name == null || memberAccess.Expression == null)
                return false;

            // if this node is annotated as being a SpecialType, let's use this information.
            if (memberAccess.HasAnnotations(SpecialTypeAnnotation.Kind))
            {
                replacementNode = SyntaxFactory.PredefinedType(
                    SyntaxFactory.Token(
                        memberAccess.GetLeadingTrivia(),
                        GetPredefinedKeywordKind(SpecialTypeAnnotation.GetSpecialType(memberAccess.GetAnnotations(SpecialTypeAnnotation.Kind).First())),
                        memberAccess.GetTrailingTrivia()));

                issueSpan = memberAccess.Span;
                return true;
            }

            // See https://github.com/dotnet/roslyn/issues/40974
            //
            // To be very safe, we only support simplifying code that bound to a symbol without any
            // sort of problems.  We could potentially relax this in the future.  However, we would
            // need to be very careful about the implications of us offering to fixup 'broken' code 
            // in a manner that might end up making things worse or confusing the user.
            var symbol = SimplificationHelpers.GetOriginalSymbolInfo(semanticModel, memberAccess);
            if (symbol == null)
                return false;

            if (memberAccess.Expression.IsKind(SyntaxKind.ThisExpression) &&
                !SimplificationHelpers.ShouldSimplifyThisOrMeMemberAccessExpression(semanticModel, optionSet, symbol))
            {
                return false;
            }

            // if this node is on the left side, we could simplify to aliases
            if (!memberAccess.IsRightSideOfDot())
            {
                // Check if we need to replace this syntax with an alias identifier
                if (TryReplaceExpressionWithAlias(
                        memberAccess, semanticModel, symbol,
                        cancellationToken, out var aliasReplacement))
                {
                    // get the token text as it appears in source code to preserve e.g. unicode character escaping
                    var text = aliasReplacement.Name;
                    var syntaxRef = aliasReplacement.DeclaringSyntaxReferences.FirstOrDefault();

                    if (syntaxRef != null)
                    {
                        var declIdentifier = ((UsingDirectiveSyntax)syntaxRef.GetSyntax(cancellationToken)).Alias.Name.Identifier;
                        text = declIdentifier.IsVerbatimIdentifier() ? declIdentifier.ToString().Substring(1) : declIdentifier.ToString();
                    }

                    replacementNode = SyntaxFactory.IdentifierName(
                                        memberAccess.Name.Identifier.CopyAnnotationsTo(SyntaxFactory.Identifier(
                                            memberAccess.GetLeadingTrivia(),
                                            SyntaxKind.IdentifierToken,
                                            text,
                                            aliasReplacement.Name,
                                            memberAccess.GetTrailingTrivia())));

                    replacementNode = memberAccess.CopyAnnotationsTo(replacementNode);
                    replacementNode = memberAccess.Name.CopyAnnotationsTo(replacementNode);

                    issueSpan = memberAccess.Span;

                    // In case the alias name is the same as the last name of the alias target, we only include 
                    // the left part of the name in the unnecessary span to Not confuse uses.
                    if (memberAccess.Name.Identifier.ValueText == ((IdentifierNameSyntax)replacementNode).Identifier.ValueText)
                    {
                        issueSpan = memberAccess.Expression.Span;
                    }

                    return true;
                }

                // Check if the Expression can be replaced by Predefined Type keyword
                if (PreferPredefinedTypeKeywordInMemberAccess(memberAccess, optionSet, semanticModel))
                {
                    if (symbol != null && symbol.IsKind(SymbolKind.NamedType))
                    {
                        var keywordKind = GetPredefinedKeywordKind(((INamedTypeSymbol)symbol).SpecialType);
                        if (keywordKind != SyntaxKind.None)
                        {
                            replacementNode = CreatePredefinedTypeSyntax(memberAccess, keywordKind);

                            replacementNode = replacementNode
                                .WithAdditionalAnnotations<TypeSyntax>(new SyntaxAnnotation(
                                    nameof(CodeStyleOptions2.PreferIntrinsicPredefinedTypeKeywordInMemberAccess)));

                            issueSpan = memberAccess.Span; // we want to show the whole expression as unnecessary

                            return true;
                        }
                    }
                }
            }

            // Try to eliminate cases without actually calling CanReplaceWithReducedName. For expressions of the form
            // 'this.Name' or 'base.Name', no additional check here is required.
            if (!memberAccess.Expression.IsKind(SyntaxKind.ThisExpression, SyntaxKind.BaseExpression))
            {
                GetReplacementCandidates(
                    semanticModel,
                    memberAccess,
                    symbol,
                    out var speculativeSymbols,
                    out var speculativeNamespacesAndTypes);

                if (!IsReplacementCandidate(symbol, speculativeSymbols, speculativeNamespacesAndTypes))
                {
                    return false;
                }
            }

            replacementNode = memberAccess.GetNameWithTriviaMoved();
            issueSpan = memberAccess.Expression.Span;

            return CanReplaceWithReducedName(
                memberAccess, replacementNode, semanticModel, symbol, cancellationToken);
        }