in resharper/resharper-unity/src/Unity/CSharp/Feature/Services/CodeCompletion/UnityEventFunctionRule.cs [735:860]
TextLookupRanges ComputeMemberReplaceRanges(TreeOffset startOffset)
{
foreach (var treeNode in context.NodeInFile.ContainingNodes(returnThis: true))
{
if (IsDeclarationToReplace(treeNode))
{
return RangesForDeclaration(treeNode);
}
if (treeNode.IsFiltered())
{
var prevMeaningfulSibling = treeNode.GetPreviousMeaningfulSiblingThroughWhitespaceAndComments();
if (prevMeaningfulSibling != null
&& IsDeclarationToReplace(prevMeaningfulSibling)
&& (!startOffset.IsValid() || prevMeaningfulSibling.GetTreeStartOffset() >= startOffset))
{
return RangesForDeclaration(prevMeaningfulSibling);
}
var nextMeaningfulSibling = treeNode.GetNextMeaningfulSibling();
if (nextMeaningfulSibling != null && IsDeclarationToReplace(nextMeaningfulSibling))
{
return RangesForDeclaration(nextMeaningfulSibling);
}
}
if (treeNode is IFieldDeclaration field)
{
var range = context.CompletionRanges.ReplaceRange;
if (field.GetPreviousMeaningfulSibling() is ITypeUsage typeUsage)
{
range = range.SetStartTo(typeUsage.GetDocumentStartOffset());
}
return new TextLookupRanges(range, range);
}
if (treeNode is ICSharpTypeMemberDeclaration)
{
return context.CompletionRanges;
}
}
return null;
TextLookupRanges RangesForDeclaration(ITreeNode treeNode)
{
var elementRange = ComputeReplaceRangeForDeclaration(treeNode);
if (!elementRange.IsValid()) return null;
return CodeCompletionContextProviderBase.GetTextLookupRanges(context.BasicContext, elementRange);
}
DocumentRange ComputeReplaceRangeForDeclaration(ITreeNode declaration)
{
var startOffsetRange = new DocumentRange(GetDeclarationStartDocumentOffset(declaration));
var selectedRange = context.BasicContext.SelectedRange;
var anchorDeclaration = GetAnchorDeclaration(declaration);
var elementRange = startOffsetRange.Join(selectedRange)
.JoinRight(new DocumentRange(anchorDeclaration.GetDocumentEndOffset()));
if (!elementRange.IsValid())
{
elementRange = startOffsetRange.Join(selectedRange);
}
if (!elementRange.IsValid()) return DocumentRange.InvalidRange;
var anchorDeclarationNameRange = GetDeclarationNameRange(anchorDeclaration);
if (anchorDeclarationNameRange.IsValid())
{
var declarationNameLine = anchorDeclarationNameRange.StartOffset.ToDocumentCoords().Line;
var selectionLine = selectedRange.EndOffset.ToDocumentCoords().Line;
if (declarationNameLine != selectionLine)
{
return elementRange.SetEndTo(selectedRange.EndOffset);
}
}
return elementRange;
}
DocumentOffset GetDeclarationStartDocumentOffset(ITreeNode declaration)
{
// note: do not include attributes into member range
var firstChild = declaration.GetNextMeaningfulChild(null);
if (firstChild is IDocCommentBlock)
firstChild = firstChild.GetNextMeaningfulSibling();
if (firstChild is IAttributeSectionList)
firstChild = firstChild.GetNextMeaningfulSibling();
return (firstChild ?? declaration).GetDocumentStartOffset();
}
ITreeNode GetAnchorDeclaration(ITreeNode declaration)
{
if (declaration is IMethodDeclaration unfinishedMethod
&& unfinishedMethod.NameIdentifier == null
&& unfinishedMethod.LPar == null
&& unfinishedMethod.ModifiersList == null
&& unfinishedMethod.TypeUsage != null)
{
var nextDeclaration = unfinishedMethod.GetNextMeaningfulSibling();
if (IsDeclarationToReplace(nextDeclaration))
return nextDeclaration;
}
return declaration;
}
DocumentRange GetDeclarationNameRange(ITreeNode declaration)
{
switch (declaration)
{
case IMultipleFieldDeclaration fieldDecl:
return fieldDecl.DeclaratorsEnumerable.FirstOrDefault().GetDocumentRange();
case IDeclaration decl:
return decl.GetNameDocumentRange();
default:
return declaration.GetDocumentRange();
}
}
}