2016-06-13 6 views
1
public void SomeMethod(string sampleString) 
{ var helloworld = sampleString; } 

특정 심볼이 로컬 변수, 클래스 필드 또는 메소드 매개 변수인지 여부를 확인할 수 있습니까? 예 : sampleString에서 FindSymbolAtPosition을 호출하면 sampleString 심볼이 메서드의 매개 변수 또는 변수라는 것을 알 수 있습니까?이해/기호 유형 가져 오기?

편집는 다음 요구 사항은 로슬린

건물 메신저 내 정적 코드 분석 도구를, 에서 코딩 시간 일을해야한다는 것입니다
+0

입니다. –

답변

3

당신은 속성을 통해 직접 얻을 수 없습니다. 그러나이 같은 방법의 맥락에서 그것을 얻을 수 있습니다

static bool IsParameter(IdentifierNameSyntax name) 
{ 
    SyntaxNode node = name; 
    while (node != null && !(node is MethodDeclarationSyntax)) 
    { 
     node = node.Parent; 
    } 

    var method = node as MethodDeclarationSyntax; 
    if (method != null) 
    { 
     return method 
      .ParameterList 
      .Parameters 
      .Any(p => p.Identifier.Text.Equals(name.Identifier.Text)); 
    } 

    return false;    
} 

변수의 방법 컨텍스트를 얻고, .ParameterList의 모든 매개 변수는 식별자와 일치하는지 확인 .Parent 사용.

UPDATE 코드가 작동하고 증명 :

SyntaxTree tree = CSharpSyntaxTree.ParseText(
    @"using System; 
    using System.Collections; 
    using System.Linq; 
    using System.Text; 

    namespace HelloWorld 
    { 
     class Program 
     { 
      static void Main(string i) 
      { 
       var j = ""1""; 
       var k = i + j; 
      } 
     } 
    }"); 

var root = (CompilationUnitSyntax)tree.GetRoot(); 
var ns = root.Members[0] as NamespaceDeclarationSyntax; 
var cls = ns.Members[0] as ClassDeclarationSyntax; 
var method = cls.Members[0] as MethodDeclarationSyntax; 
var statement = method.Body.Statements[1] as LocalDeclarationStatementSyntax; 
var variable = statement.Declaration.Variables[0]; 
var binary = variable.Initializer.Value as BinaryExpressionSyntax; 
var vari = binary.Left as IdentifierNameSyntax; 
var varj = binary.Right as IdentifierNameSyntax; 
Console.WriteLine(IsParameter(vari)); //True 
Console.WriteLine(IsParameter(varj)); //False 

편집 @JeroenVannevel의 의견에 자료를, 우리는 SemanticModel.GetSymbolInfo를 사용할 수 있습니다.

var compilation = CSharpCompilation.Create("test", new[] { tree });     
var semanticModel = compilation.GetSemanticModel(tree, true); 
var symboli = semanticModel.GetSymbolInfo(vari); 
var symbolj = semanticModel.GetSymbolInfo(varj); 
//check symboli.Symbol.OriginalDefinition.Kind == SymbolKind.Parameter 
+0

네,하지만 이것은 문자열 비교를 통해 이루어 졌는데, 식별자 이름으로 비교하는 것보다 API를 더 잘 사용하는 것이 더 흥미 롭습니다. 그래도 고마워. –

+0

@KimKangIn 사람이 식별자가 매개 변수인지 여부를 어떻게 알 수 있습니까? 매개 변수 목록과 비교하여 식별자 이름을 비교하는 것이 올바른 (그리고 아마도 유일한) 방법이라는 것을 의미합니다. –

+1

식별자로 비교하고 싶지 않다면 (동의하지 말아야 함) 매개 변수의 기호를 가져 와서 로컬 변수의 기호와 비교하면됩니다. 'GetDeclaredSymbol'과'GetSymbolInfo'를 각각 사용하십시오. –

-3

당신이 대 클래스 필드를 처리하고 있는지를 구별 할 수있다 메소드의 매개 변수 또는 키워드 this를 사용하는 지역 변수. sampleString이라는 클래스 필드 문자열이 있고 로컬 변수/메서드 매개 변수 대신 클래스 필드를 참조하려면 this.sampleString을 사용하여 참조하십시오. 키워드 (this)없이 로컬 변수/메소드 매개 변수를 sampleString으로 참조합니다. 지역 변수 및 메소드 매개 변수의 측면에서 동일한 메소드 내에서 동일한 이름의 로컬 변수 및 메소드 매개 변수를 가질 수 없습니다. 위의 코드를 사용하면 sampleString 매개 변수를 참조하게됩니다.

+0

그건 OP가 요구하는 것이 아닙니다. – MickyD

+0

간접적으로 말하지만 그것은 분명히 충분히 설명하지 못했을 것입니다.메서드 내에서 sampleString에 대해 FindSymbolAtPosition을 사용하는 경우 클래스 필드가 아닌 매개 변수에서이를 사용할 것입니다. this.sampleString에서 FindSymbolAtPosition을 사용한 경우 클래스 필드에서이 문자열을 사용하게됩니다. 여기에는 지역 변수와 sampleString이라는 클래스 필드가 있다고 가정합니다. 처리되는 매개 변수는 지역 변수와 유사하게 다르기 때문에 동일한 이름으로 동일한 메소드 내에서 매개 변수와 로컬 변수를 선언 할 수 없습니다. –

+0

현재 코드 스 니펫에서 그는 매개 변수를 언급하는 데 의심의 여지가 없습니다. 클래스 필드와 같은 이름을 공유하는 메서드 내에 매개 변수/로컬 변수가 있고 키워드 (this)를 사용하지 않고이 변수를 호출하면 클래스 필드가 아니라 매개 변수/로컬 변수가 항상 호출됩니다. –

-2

다음 코드를 사용하여 클래스 및 매개 변수의 필드 정보를 가져올 수 있습니다. 단, 메서드 필드의 검색은 사용할 수 없습니다. 이 코드는 리플렉션을 사용하여 어셈블리 정보를 쿼리하고 결과를 열거하고 비교합니다. var helloworld = sampleString;에, 문이 sampleString 경우 매개 변수 또는 아니라고 아무 맥락이 없기 때문에

static class Program 
{ 
    static void Main(string[] args) 
    { 

     SomeMethod("Hello, World!!!"); 

     Type testType = typeof(Program); 
     FieldInfo[] fieldInfo = testType.GetFields(); 
     MethodInfo methodInfo = testType.GetMethod("SomeMethod"); 

     Console.WriteLine("Parameter type:{0}", TypeOfField(fieldInfo, methodInfo, "sampleString")); 
     Console.WriteLine("Parameter type:{0}", TypeOfField(fieldInfo, methodInfo, "classField")); 
     Console.WriteLine("Parameter type:{0}", TypeOfField(fieldInfo, methodInfo, "helloWorld")); 
     Console.WriteLine("Parameter type:{0}", TypeOfField(fieldInfo, methodInfo, "nonexistentVariable")); 

    } 

    public static string classField = "Hello, World!!!"; 

    public static void SomeMethod(string sampleString) 
    { 
     string helloWorld = sampleString; 
    } 

    public static string TypeOfField(FieldInfo[] fieldInfo, MethodInfo methodInfo, string fieldName) 
    { 
     if (IsClassField(fieldInfo, fieldName)) 
     { 
      return "Class Field"; 
     } 
     else if (IsParameter(methodInfo, fieldName)) 
     { 
      return "Parameter"; 
     } 
     else 
     { 
      return "Cannot determine"; 
     } 
    } 

    private static bool IsClassField(FieldInfo[] fieldInfo, string classFieldName) 
    { 
     bool isClassField = false; 

     foreach (var item in fieldInfo) 
     { 
      if (item.Name == classFieldName) 
      { 
       isClassField = true; 
       break; 
      } 
     } 
     return isClassField; 
    } 

    private static bool IsParameter(MethodInfo methodInfo, string parameterName) 
    { 
     bool isParameter = false; 
     ParameterInfo[] paramInfo = methodInfo.GetParameters(); 
     foreach (var item in paramInfo) 
     { 
      if (item.Name == parameterName) 
      { 
       isParameter = true; 
       break; 
      } 
     } 
     return isParameter; 
    } 
} 
+1

반사는 Roslyn과 완전히 별개입니다. 이것은 질문에 대답하지 않습니다. –

+0

@JeroenVannevel 원래 질문의 일부가 아니 었습니다. –

+1

항상 Roslyn으로 태그되었으며 OP에 언급 된 방법도 Roslyn의 일부입니다. –

0

그것 IdentifierNameSyntaxMemberAccessExpressionSyntax의 이름이며 parameter 같은 identifier이있는 경우 다음 잘못 그것입니다 parameter하더라도이라고 결론을 내릴 것, 상상, 구문 또는 텍스트로 식별자를 비교하는 것은 잘못 a member. SymbolKind이 무엇인지 확인하려면 SemanticModel으로 작업해야합니다. 선언시 SemanticModel.GetDeclaredSymbol을, 기호 사용시 SemanticModel.GetSymbolInfo().Symbol을 사용할 수 있습니다. ISymbol을 찾으면 그 종류를 쉽게 결정할 수 있습니다. 서로 다른 기호에는 자체 하위 유형이 있습니다. 예를 들어 ITypeSymbol의 유형이 Class, Struct, Interface, 등인 지 확인하기 위해 TypeKind 속성이 있으므로 확인해야합니다. roslyn으로 구축 한 내 정적 코드 분석 도구의 경우 코드 시간은