public sealed record DeclarationData()

in src/dotnet/ReSharperPlugin.DotNetDisassembler/AsmMethodLocator.cs [18:100]


public sealed record DeclarationData(
    DisasmTarget Target,
    string FilePath,
    long FileStamp,
    JitDisasmProjectContext ProjectContext);

[SolutionComponent(Instantiation.DemandAnyThreadSafe)]
public class AsmMethodLocator(
    ISolution solution,
    IPsiCachesState psiCachesState)
{
    private static readonly ILogger Logger = GetLogger<AsmMethodLocator>();

    public Result<DeclarationData, Error> FindDeclarationAtCaret(ITextControl textControl)
    {
        if (!psiCachesState.IsInitialUpdateFinished.Value)
        {
            Logger.Verbose("Waiting for PSI caches to initialize");
            return Result.FailWithValue(new Error(AsmViewerErrorCode.UpdateCancelled));
        }

        return solution.Locks.ExecuteWithReadLock<Result<DeclarationData, Error>>(() =>
        {
            if (!textControl.Lifetime.IsAlive)
            {
                Logger.Verbose("Text control is no longer alive");
                return Result.FailWithValue(new Error(AsmViewerErrorCode.UpdateCancelled));
            }

            var psiEditorView = new PsiEditorView(solution, textControl);

            var psiSourceFile = textControl.Document.GetPsiSourceFile(solution);
            if (psiSourceFile == null || !psiSourceFile.PrimaryPsiLanguage.Is<CSharpLanguage>())
            {
                Logger.Verbose("File is not a C# source file");
                return Result.FailWithValue(new Error(AsmViewerErrorCode.UnsupportedLanguage));
            }

            var declaration = JitDisasmTargetUtils.FindValidDeclaration(psiEditorView);
            if (declaration == null)
            {
                Logger.Verbose("Caret is not positioned on a method or class declaration");
                return Result.FailWithValue(new Error(AsmViewerErrorCode.InvalidCaretPosition));
            }

            var declaredElement = declaration.DeclaredElement;
            if (declaredElement == null)
            {
                Logger.Verbose("Declaration has no associated symbol (possibly incomplete code)");
                return Result.FailWithValue(new Error(AsmViewerErrorCode.InvalidCaretPosition));
            }

            var sourceFile = declaration.GetSourceFile();
            if (sourceFile == null)
            {
                Logger.Verbose("Declaration is not associated with a source file");
                return Result.FailWithValue(new Error(AsmViewerErrorCode.PsiSourceFileUnavailable));
            }

            var location = sourceFile.GetLocation();
            if (location.IsEmpty)
            {
                Logger.Verbose("Source file '{0}' has no path on disk", sourceFile.Name);
                return Result.FailWithValue(new Error(AsmViewerErrorCode.SourceFileNotFound));
            }

            var project = declaration.GetProject();
            if (project == null)
            {
                Logger.Verbose("Source file '{0}' is not part of any project", location.FullPath);
                return Result.FailWithValue(new Error(AsmViewerErrorCode.SourceFileNotFound));
            }

            var target = JitDisasmTargetUtils.GetTarget(declaredElement);
            var filePath = location.FullPath;
            var fileStamp = location.FileModificationTimeUtc.Ticks;
            var projectContext = JitDisasmProjectContextFactory.Create(project);

            Logger.Info("Found target '{0}' in '{1}'", target.MemberFilter, filePath);
            return Result.Success(new DeclarationData(target, filePath, fileStamp, projectContext));
        });
    }
}