Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 90 additions & 11 deletions plugins/csharp/parser/src_csharp/AstVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,35 @@ private ulong fnvHash(string data_)
}

return hash;
}
}

// Deterministic replacement for GetHashCode(), which is reference based
// for syntax nodes and randomized per process for strings. Both would
// give different ids for the same entity on every parse.
private long stableHash(string data_)
{
return unchecked((long)fnvHash(data_));
}

private long getEntityHash(SyntaxNode node)
{
string[] properties =
{
node.SyntaxTree.FilePath,":",
node.Kind().ToString(),":",
node.Span.Start.ToString(),":",
node.Span.End.ToString()
};

return stableHash(string.Concat(properties));
}

private ulong getAstNodeId(SyntaxNode node){
CsharpAstNode astNode = new CsharpAstNode
{
AstValue = node.ToString(),
RawKind = node.Kind(),
EntityHash = node.GetHashCode(),
EntityHash = getEntityHash(node),
AstType = AstTypeEnum.Declaration
};
astNode.SetLocation(node.SyntaxTree.GetLineSpan(node.Span));
Expand All @@ -86,7 +107,7 @@ private CsharpAstNode AstNode(SyntaxNode node, AstSymbolTypeEnum type, AstTypeEn
{
AstValue = node.ToString(),
RawKind = node.Kind(),
EntityHash = node.GetHashCode(),
EntityHash = getEntityHash(node),
AstSymbolType = type,
AstType = astType,
Accessibility = acc
Expand Down Expand Up @@ -616,7 +637,7 @@ private void VisitMethodDecl(MethodDeclarationSyntax node, CsharpAstNode parent)
QualifiedName = qName,
QualifiedType = qType,
DocumentationCommentXML = Model.GetDeclaredSymbol(node).GetDocumentationCommentXml(),
TypeHash = qType.GetHashCode(),
TypeHash = stableHash(qType),
EntityHash = astNode.EntityHash,
ParentNode = parent,
MethodType = MethodTypeEnum.Method
Expand Down Expand Up @@ -666,7 +687,7 @@ private void VisitOperatorDecl(OperatorDeclarationSyntax node, CsharpAstNode par
QualifiedName = qName,
QualifiedType = qType,
DocumentationCommentXML = Model.GetDeclaredSymbol(node).GetDocumentationCommentXml(),
TypeHash = qType.GetHashCode(),
TypeHash = stableHash(qType),
EntityHash = astNode.EntityHash,
ParentNode = parent,
MethodType = MethodTypeEnum.Operator
Expand Down Expand Up @@ -704,7 +725,7 @@ private void VisitMethodParameters(SeparatedSyntaxList<ParameterSyntax> paramete
AstNode = astNode,
Name = param.Identifier.Text,
QualifiedType = paramQType,
TypeHash = paramQType.GetHashCode(),
TypeHash = stableHash(paramQType),
EntityHash = astNode.EntityHash,
ParentNode = parent,
VariableType = VariableTypeEnum.Parameter
Expand Down Expand Up @@ -752,7 +773,7 @@ private void VisitVariableDecl(VariableDeclarationSyntax node, CsharpAstNode par
AstNode = astNode,
Name = variable.Identifier.Text,
QualifiedType = varQType,
TypeHash = varQType.GetHashCode(),
TypeHash = stableHash(varQType),
DocumentationCommentXML = Model.GetDeclaredSymbol(variable).GetDocumentationCommentXml(),
EntityHash = astNode.EntityHash,
VariableType = isLINQvar ? VariableTypeEnum.LINQ : VariableTypeEnum.Variable,
Expand All @@ -779,7 +800,7 @@ private void VisitPropertyDecl(PropertyDeclarationSyntax node, CsharpAstNode par
AstNode = astNode,
Name = node.Identifier.Text,
QualifiedType = varQType,
TypeHash = varQType.GetHashCode(),
TypeHash = stableHash(varQType),
VariableType = VariableTypeEnum.Property,
DocumentationCommentXML = Model.GetDeclaredSymbol(node).GetDocumentationCommentXml(),
EntityHash = astNode.EntityHash,
Expand Down Expand Up @@ -951,11 +972,69 @@ public override void VisitInvocationExpression(InvocationExpressionSyntax node)
DbContext.CsharpEtcEntitys.Add(invoc);
}
}
}
}
}
}

VisitMethodInvocation(node);

base.VisitInvocationExpression(node);
}
}

// Records an invocation whose DeclaratorNodeId points to the declaration
// of the called method. This is what the Callee / Caller references and
// the function call diagram rely on.
private void VisitMethodInvocation(InvocationExpressionSyntax node)
{
SimpleNameSyntax name = node.Expression switch
{
MemberAccessExpressionSyntax memberAccess => memberAccess.Name,
MemberBindingExpressionSyntax memberBinding => memberBinding.Name,
SimpleNameSyntax simpleName => simpleName,
_ => null
};

// Unqualified Foo() calls are already recorded by VisitIdentifierName.
if (name == null || (name == node.Expression && name is IdentifierNameSyntax))
return;

var method = Model.GetSymbolInfo(node).Symbol as IMethodSymbol;
if (method == null)
return;

method = (method.ReducedFrom ?? method).OriginalDefinition;
method = method.PartialImplementationPart ?? method;

var declaration = method.DeclaringSyntaxReferences
.Select(r => r.GetSyntax())
.FirstOrDefault(s => s is BaseMethodDeclarationSyntax);
if (declaration == null)
return;

var type = "";
try
{
var info = Model.GetTypeInfo(node).ConvertedType;
if (info != null) type = info.Name;
}
catch (Exception)
{
FullyParsed = false;
}

var declaratorNodeId = getAstNodeId(declaration);
var astNode = AstNode(name, AstSymbolTypeEnum.EtcEntity, AstTypeEnum.Usage);
CsharpEtcEntity invoc = new CsharpEtcEntity
{
AstNode = astNode,
EntityHash = astNode.EntityHash,
EtcEntityType = EtcEntityTypeEnum.Invocation,
DeclaratorNodeId = declaratorNodeId,
Name = name.Identifier.Text,
QualifiedName = method.ToString(),
QualifiedType = type
};
DbContext.CsharpEtcEntitys.Add(invoc);
}

public override void VisitIdentifierName(IdentifierNameSyntax node)
{
Expand Down
1 change: 1 addition & 0 deletions plugins/csharp/service/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ add_subdirectory(src_csharp)

add_library(csharpservice SHARED
src/csharpservice.cpp
src/csharpdiagram.cpp
src/plugin.cpp)

target_compile_options(csharpservice PUBLIC -Wno-unknown-pragmas)
Expand Down
3 changes: 0 additions & 3 deletions plugins/csharp/service/csharpservice.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ service CsharpService
map<string, i32> getDiagramTypes(1:common.AstNodeId astNodeId)
throws (1:common.InvalidId ex)

string getDiagram(1:common.AstNodeId astNodeId, 2:i32 diagramId)
throws (1:common.InvalidId exId, 2:common.Timeout exLong)

list<language.SyntaxHighlight> getSyntaxHighlight(
1:common.FileRange range,
2:list<string> content)
Expand Down
22 changes: 13 additions & 9 deletions plugins/csharp/service/include/service/csharpservice.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,6 @@ class CSharpQueryHandler : public CsharpServiceIf
_service -> getDiagramTypes(return_, astNodeId_);
}

void getDiagram(
std::string& return_,
const core::AstNodeId& astNodeId_,
const std::int32_t diagramId_) override
{
_service -> getDiagram(return_, astNodeId_, diagramId_);
}

void getSyntaxHighlight(
std::vector<language::SyntaxHighlight>& return_,
const core::FileRange& range_,
Expand Down Expand Up @@ -219,7 +211,7 @@ using TransportException = apache::thrift::transport::TTransportException;

class CsharpServiceHandler : virtual public LanguageServiceIf
{
friend class Diagram;
friend class CsharpDiagram;

public:
CsharpServiceHandler(
Expand Down Expand Up @@ -323,6 +315,18 @@ class CsharpServiceHandler : virtual public LanguageServiceIf
const core::FileRange& range_) override;

private:
// Must be kept in sync with CSharpServiceEnums.cs.
enum DiagramType
{
FUNCTION_CALL
};

enum ReferenceType
{
CALLEE = 5,
CALLER = 6
};

std::shared_ptr<odb::database> _db;
util::OdbTransaction _transaction;

Expand Down
Loading
Loading