public override ExpressionSyntax VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
        {
            node = node.WithExpression(Visit(node.Expression));

            var parentIndentWidth = node
                                    .GetLeadingTrivia()
                                    .FirstOrDefault(x => x.IsKind(SyntaxKind.WhitespaceTrivia))
                                    .Span
                                    .Length;

            if (!node.Expression.GetTrailingTrivia().Any(x => x.IsKind(SyntaxKind.EndOfLineTrivia)))
            {
                node = node.WithExpression(
                    node.Expression.WithTrailingTrivia(
                        new[] { SyntaxFactory.EndOfLine("\n") }));
            }

            var oldWhitespaceTrivia = node.OperatorToken.LeadingTrivia.FirstOrDefault(x => x.IsKind(SyntaxKind.WhitespaceTrivia));

            if (oldWhitespaceTrivia.Span.Length != parentIndentWidth + 4)
            {
                var newWhitespaceTrivia = SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, new string(' ', parentIndentWidth + 4));
                node = node
                       .WithOperatorToken(
                    node.OperatorToken.WithLeadingTrivia(newWhitespaceTrivia));
            }

            return(node);
        }
            SyntaxNode GetMemberAccessWithoutThis(MemberAccessExpressionSyntax thisItemAsMemberAccessException)
            {
                var thisItemAsMemberAccessExceptionSymbol = semanticModel.GetSymbolInfo(thisItemAsMemberAccessException).Symbol;

                if (thisItemAsMemberAccessExceptionSymbol is IFieldSymbol && !CheckOption((int)RemoveExtraThisKeyword.CleanupTypes.Remove_From_Fields_Call))
                {
                    return(null);
                }
                if (thisItemAsMemberAccessExceptionSymbol is IPropertySymbol && !CheckOption((int)RemoveExtraThisKeyword.CleanupTypes.Remove_From_Properties_Call))
                {
                    return(null);
                }
                if (thisItemAsMemberAccessExceptionSymbol is IMethodSymbol && !CheckOption((int)RemoveExtraThisKeyword.CleanupTypes.Remove_From_Method_Call))
                {
                    return(null);
                }

                var right   = thisItemAsMemberAccessException.Name;
                var symbols = semanticModel.LookupSymbols(thisItemAsMemberAccessException.SpanStart, name: right.Identifier.ValueText);

                if (symbols.Any(x => x == thisItemAsMemberAccessExceptionSymbol))
                {
                    return(right.WithLeadingTrivia(thisItemAsMemberAccessException.GetLeadingTrivia()));
                }

                return(null);
            }
Exemplo n.º 3
0
        private async Task<Document> InsertAsyncCall(Document document, MemberAccessExpressionSyntax memberAccess, CancellationToken cancellationToken)
        {
            var name = memberAccess.Name.Identifier.ValueText;
            ExpressionSyntax oldNode, newNode, newMemberAccess;
            switch (name)
            {
                case "WaitAny":
                    newMemberAccess = memberAccess.WithName((SimpleNameSyntax)SyntaxFactory.ParseName("WhenAny"));
                    break;
                case "WaitAll":
                    newMemberAccess = memberAccess.WithName((SimpleNameSyntax)SyntaxFactory.ParseName("WhenAny"));
                    break;
                case "Wait":
                    newMemberAccess = memberAccess.Expression;
                    break;
                case "Result":
                    newMemberAccess = memberAccess.Expression;
                    break;
                case "Sleep":
                    newMemberAccess = SyntaxFactory.ParseExpression("Task.Delay");
                    break;
                default:
                    newMemberAccess = memberAccess.WithName((SimpleNameSyntax)SyntaxFactory.ParseName(memberAccess.Name.Identifier.ValueText + "Async"));
                    break;
            }

            var invoc = memberAccess.Parent as InvocationExpressionSyntax;
            // WaitAny, WaitAll, Wait, Sleep, XyzAsync etc.
            if (invoc != null)
            {
                oldNode = invoc;
                newNode = name == "Wait" ? newMemberAccess : invoc.WithExpression(newMemberAccess);
            }
            // t.Result
            else
            {
                oldNode = memberAccess;
                newNode = newMemberAccess;
            }

            newNode = SyntaxFactory.AwaitExpression(newNode)
                .WithAdditionalAnnotations(Formatter.Annotation)
                .WithLeadingTrivia(memberAccess.GetLeadingTrivia())
                .WithTrailingTrivia(memberAccess.GetTrailingTrivia());

            if (oldNode.Parent.Kind() == SyntaxKind.SimpleMemberAccessExpression)
            {
                newNode = SyntaxFactory.ParenthesizedExpression(newNode);
            }

            var root = await document.GetSyntaxRootAsync().ConfigureAwait(false);
            var newRoot = root.ReplaceNode(oldNode, newNode);
            return document.WithSyntaxRoot(newRoot);
        }
Exemplo n.º 4
0
            private SyntaxNode GetMemberAccessWithoutThis(MemberAccessExpressionSyntax thisItemAsMemberAccessException)
            {
                var right   = thisItemAsMemberAccessException.Name;
                var symbols = semanticModel.LookupSymbols(thisItemAsMemberAccessException.SpanStart, name: right.Identifier.ValueText);
                var thisItemAsMemberAccessExceptionSymbol = semanticModel.GetSymbolInfo(thisItemAsMemberAccessException).Symbol;

                if (symbols.Any(x => x == thisItemAsMemberAccessExceptionSymbol))
                {
                    return(right.WithLeadingTrivia(thisItemAsMemberAccessException.GetLeadingTrivia()));
                }
                return(null);
            }
 private static SyntaxTriviaList GetLeadingTriviaForSimplifiedMemberAccess(MemberAccessExpressionSyntax memberAccess)
 {
     // We want to include any user-typed trivia that may be present between the 'Expression', 'OperatorToken' and 'Identifier' of the MemberAccessExpression.
     // However, we don't want to include any elastic trivia that may have been introduced by the expander in these locations. This is to avoid triggering
     // aggressive formatting. Otherwise, formatter will see this elastic trivia added by the expander and use that as a cue to introduce unnecessary blank lines
     // etc. around the user's original code.
     return(SyntaxFactory.TriviaList(WithoutElasticTrivia(
                                         memberAccess.GetLeadingTrivia()
                                         .AddRange(memberAccess.Expression.GetTrailingTrivia())
                                         .AddRange(memberAccess.OperatorToken.LeadingTrivia)
                                         .AddRange(memberAccess.OperatorToken.TrailingTrivia)
                                         .AddRange(memberAccess.Name.GetLeadingTrivia()))));
 }
Exemplo n.º 6
0
        public override SyntaxNode VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
        {
            node = (MemberAccessExpressionSyntax)base.VisitMemberAccessExpression(node);

            var type = _context.GetNodeContainingClassType(node);

            if (type == _type && node.Name.ToString() == _memberName)
            {
                node = node
                       .WithName(SyntaxFactory.IdentifierName(_newName))
                       .WithLeadingTrivia(node.GetLeadingTrivia())
                       .WithTrailingTrivia(node.GetTrailingTrivia());

                node = node.CopyAnnotationsTo(node);
            }

            return(node);
        }
Exemplo n.º 7
0
        public override SyntaxNode VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
        {
            var symbol = semanticModel.GetSymbolInfo(node.Expression).Symbol;

            var parent = node.Parent;

            while (parent != null && !(parent is TypeDeclarationSyntax))
            {
                parent = parent.Parent;
            }

            ITypeSymbol thisType = null;

            if (parent is TypeDeclarationSyntax)
            {
                thisType = this.semanticModel.GetDeclaredSymbol(parent) as ITypeSymbol;
            }

            node = (MemberAccessExpressionSyntax)base.VisitMemberAccessExpression(node);

            if (node.Expression is IdentifierNameSyntax && symbol != null && symbol.IsStatic && symbol.ContainingType != null && thisType != null && !thisType.InheritsFromOrEquals(symbol.ContainingType) && (symbol is IMethodSymbol || symbol is IPropertySymbol || symbol is IFieldSymbol || symbol is IEventSymbol))
            {
                return(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(SyntaxFactory.Identifier(node.GetLeadingTrivia(), symbol.FullyQualifiedName(), node.GetTrailingTrivia())), node.OperatorToken, node.Name));
            }

            return(node);
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        private SyntaxNode GetRoleMethodInvocation(MemberAccessExpressionSyntax node)
        {
            var expression = Visit(node.Expression);
            if (node.Expression != expression)
            {
                node = node.ReplaceNode(node.Expression, expression);
            }
            if (IsRoleMethodInvocation(node))
            {
                var methodName = ((SimpleNameSyntax)node.Name).Identifier.ValueText;
                return Syntax.IdentifierName("self__" + GetRoleName(node.Expression) + "__" + methodName).WithLeadingTrivia(node.GetLeadingTrivia());

            }
            return node;
        }
Exemplo n.º 10
0
        public override SyntaxNode VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
        {
            var symbol = semanticModel.GetSymbolInfo(node.Expression).Symbol;

            node = (MemberAccessExpressionSyntax)base.VisitMemberAccessExpression(node);

            if (node.Expression is IdentifierNameSyntax && symbol != null && symbol.IsStatic && symbol.ContainingType != null && (symbol is IMethodSymbol || symbol is IPropertySymbol || symbol is IFieldSymbol || symbol is IEventSymbol))
            {
                return(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(SyntaxFactory.Identifier(node.GetLeadingTrivia(), symbol.FullyQualifiedName(), node.GetTrailingTrivia())), node.OperatorToken, node.Name));
            }

            return(node);
        }
Exemplo n.º 11
0
        private async Task <Document> InsertAsyncCall(Document document, MemberAccessExpressionSyntax memberAccess, CancellationToken cancellationToken)
        {
            var name = memberAccess.Name.Identifier.ValueText;
            ExpressionSyntax oldNode, newNode, newMemberAccess;

            switch (name)
            {
            case "WaitAny":
                newMemberAccess = memberAccess.WithName((SimpleNameSyntax)SyntaxFactory.ParseName("WhenAny"));
                break;

            case "WaitAll":
                newMemberAccess = memberAccess.WithName((SimpleNameSyntax)SyntaxFactory.ParseName("WhenAny"));
                break;

            case "Wait":
                newMemberAccess = memberAccess.Expression;
                break;

            case "Result":
                newMemberAccess = memberAccess.Expression;
                break;

            case "Sleep":
                newMemberAccess = SyntaxFactory.ParseExpression("Task.Delay");
                break;

            default:
                newMemberAccess = memberAccess.WithName((SimpleNameSyntax)SyntaxFactory.ParseName(memberAccess.Name.Identifier.ValueText + "Async"));
                break;
            }

            var invoc = memberAccess.Parent as InvocationExpressionSyntax;

            // WaitAny, WaitAll, Wait, Sleep, XyzAsync etc.
            if (invoc != null)
            {
                oldNode = invoc;
                newNode = name == "Wait" ? newMemberAccess : invoc.WithExpression(newMemberAccess);
            }
            // t.Result
            else
            {
                oldNode = memberAccess;
                newNode = newMemberAccess;
            }

            newNode = SyntaxFactory.AwaitExpression(newNode)
                      .WithAdditionalAnnotations(Formatter.Annotation)
                      .WithLeadingTrivia(memberAccess.GetLeadingTrivia())
                      .WithTrailingTrivia(memberAccess.GetTrailingTrivia());

            if (oldNode.Parent.Kind() == SyntaxKind.SimpleMemberAccessExpression)
            {
                newNode = SyntaxFactory.ParenthesizedExpression(newNode);
            }

            var root = await document.GetSyntaxRootAsync().ConfigureAwait(false);

            var newRoot = root.ReplaceNode(oldNode, newNode);

            return(document.WithSyntaxRoot(newRoot));
        }
        private static async Task<Document> FixMember(Document document, MemberAccessExpressionSyntax memberAccessExpression, string apiId, string varName, CancellationToken cancellationToken)
        {
            var apiConversion = WinUIAppWindowAnalyzer.MemberApiConversions[apiId]!;
            if (apiConversion.ToApi is not IMemberDescription)
            {
                throw new InvalidOperationException($"Expecting all types in MemberApiConversions dictionary to be of type ITypeMemberDescription but found {apiConversion.ToApi.GetType()}");
            }

            var fromMember = (IMemberDescription)apiConversion.FromApi;
            var toMember = (IMemberDescription)apiConversion.ToApi;
            var (newTypeNamespace, newTypeName, newMemberName) = (toMember.TypeDescription.Namespace, toMember.TypeDescription.TypeName, toMember.MemberName);

            if (apiConversion.NeedsManualUpgradation)
            {
                var comment = SyntaxFactory.Comment(@$"
                    /* 
                        TODO {WinUIAppWindowAnalyzer.DiagnosticIdAppWindowMember}
                        Use {newTypeNamespace}.{newTypeName}.{newMemberName} instead of {fromMember.MemberName}.
                        Read: {apiConversion.DocumentationUrl}
                    */
                    ");
                var existingRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                return document.WithSyntaxRoot(existingRoot!.ReplaceNode(memberAccessExpression, memberAccessExpression.WithLeadingTrivia(comment)));
            }

            var documentEditor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
            var instance = toMember.IsStatic ? $"{newTypeNamespace}.{newTypeName}" : varName;
            if (toMember.ApiType == ApiType.PropertyApi)
            {
                var expr = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                    SyntaxFactory.ParseExpression(instance), (SimpleNameSyntax)SyntaxFactory.ParseName(newMemberName));

                documentEditor.ReplaceNode(memberAccessExpression, expr.WithLeadingTrivia(memberAccessExpression.GetLeadingTrivia()));
                return document.WithSyntaxRoot(documentEditor.GetChangedRoot());
            }

            var invocationExpression = memberAccessExpression.AncestorsAndSelf().OfType<InvocationExpressionSyntax>().First();
            var newExpression = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression($"{instance}.{newMemberName}"));
            var newExpressionArgs = newExpression.DescendantNodes().OfType<ArgumentListSyntax>().First();
            var argsToAdd = invocationExpression.DescendantNodes().OfType<ArgumentListSyntax>().First().Arguments.ToArray();
            var newArgs = newExpressionArgs.AddArguments(argsToAdd);
            var newExpressionWithArgs = newExpression.ReplaceNode(newExpressionArgs, newArgs);

            if (fromMember.ApiType == ApiType.MethodApi && toMember.ApiType == ApiType.MethodApi
                && ((MethodDescription)fromMember).IsAsync && !((MethodDescription)toMember).IsAsync)
            {
                var awaitExpression = invocationExpression.Ancestors().OfType<AwaitExpressionSyntax>().FirstOrDefault();
                if (awaitExpression is not null)
                {
                    documentEditor.ReplaceNode(awaitExpression, newExpressionWithArgs.WithLeadingTrivia(invocationExpression.GetLeadingTrivia()));
                    return document.WithSyntaxRoot(documentEditor.GetChangedRoot());
                }
            }

            documentEditor.ReplaceNode(invocationExpression, newExpressionWithArgs.WithLeadingTrivia(invocationExpression.GetLeadingTrivia()));
            return document.WithSyntaxRoot(documentEditor.GetChangedRoot());
        }
Exemplo n.º 13
0
        private SyntaxNode GetRoleMethodInvocation(MemberAccessExpressionSyntax node)
        {
            var expression = Visit(node.Expression);

            if (node.Expression != expression)
            {
                node = node.ReplaceNode(node.Expression, expression);
            }
            if (IsRoleMethodInvocation(node))
            {
                var methodName = ((SimpleNameSyntax)node.Name).Identifier.ValueText;
                return(Syntax.IdentifierName("self__" + GetRoleName(node.Expression) + "__" + methodName).WithLeadingTrivia(node.GetLeadingTrivia()));
            }
            return(node);
        }
Exemplo n.º 14
0
        public override SyntaxNode VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
        {
            var esym = m_Model.GetSymbolInfo(node).Symbol as IEventSymbol;
            var psym = m_Model.GetSymbolInfo(node).Symbol as IPropertySymbol;
            var fsym = m_Model.GetSymbolInfo(node).Symbol as IFieldSymbol;
            var msym = m_Model.GetSymbolInfo(node).Symbol as IMethodSymbol;
            var oper = m_Model.GetOperation(node);

            SyntaxNode newNode = null;
            var        name    = node.Expression as IdentifierNameSyntax;

            if (null != name)
            {
                var text = name.Identifier.Text;
                foreach (var ns in SymbolTable.Instance.Namespaces)
                {
                    if (ns == text || ns.Contains("." + text + ".") || ns.EndsWith("." + text))
                    {
                        newNode = SyntaxFactory.IdentifierName(node.Name.ToString()).WithLeadingTrivia(node.GetLeadingTrivia()).WithTrailingTrivia(node.GetTrailingTrivia());
                    }
                }
            }
            if (null == newNode)
            {
                newNode = base.VisitMemberAccessExpression(node);
            }
            bool             isExtern  = false;
            INamedTypeSymbol classType = null;

            if (null != esym && SymbolTable.Instance.IsExternSymbol(esym))
            {
                isExtern  = true;
                classType = esym.ContainingType;
                newNode   = ReportAndAttachError(newNode, string.Format("[Cs2LuaRewriter] Unsupported extern event !"));
            }
            if (null != psym && SymbolTable.Instance.IsExternSymbol(psym))
            {
                isExtern  = true;
                classType = psym.ContainingType;
                if (SymbolTable.Instance.IsIllegalProperty(psym))
                {
                    newNode = ReportAndAttachError(newNode, string.Format("[Cs2LuaRewriter] Unsupported extern property !"));
                }
            }
            if (null != fsym && SymbolTable.Instance.IsExternSymbol(fsym))
            {
                isExtern  = true;
                classType = fsym.ContainingType;
                if (SymbolTable.Instance.IsIllegalField(fsym))
                {
                    newNode = ReportAndAttachError(newNode, string.Format("[Cs2LuaRewriter] Unsupported extern field !"));
                }
            }
            if (null != msym && !(node.Parent is InvocationExpressionSyntax) && SymbolTable.Instance.IsExternSymbol(msym.ContainingType))
            {
                if (SymbolTable.Instance.IsIllegalMethod(msym))
                {
                    newNode = ReportAndAttachError(newNode, "[Cs2LuaRewriter] Unsupported extern method !");
                }
            }
            if (isExtern && null != oper)
            {
                bool legal = true;
                SymbolTable.TryRemoveNullable(ref classType);
                if (null != classType && (classType.TypeKind == TypeKind.Delegate || classType.IsGenericType && SymbolTable.Instance.IsLegalGenericType(classType, true)))
                {
                    //如果是标记为合法的泛型类或委托类型的成员,则不用再进行类型检查
                }
                else
                {
                    var type = oper.Type as INamedTypeSymbol;
                    SymbolTable.TryRemoveNullable(ref type);
                    if (null != type && SymbolTable.Instance.IsExternSymbol(type) && type.TypeKind != TypeKind.Delegate)
                    {
                        if (type.IsGenericType)
                        {
                            if (!SymbolTable.Instance.IsLegalParameterGenericType(type))
                            {
                                legal = false;
                            }
                        }
                        else
                        {
                            if (SymbolTable.Instance.IsIllegalType(type))
                            {
                                legal = false;
                            }
                        }
                    }
                }
                if (!legal)
                {
                    newNode = ReportAndAttachError(newNode, string.Format("[Cs2LuaRewriter] Unsupported extern type from member access !"));
                }
            }
            return(newNode);
        }