private bool HandleEnterAction()

in resharper/resharper-unity/src/Unity.Shaders/ShaderLab/Feature/Services/TypingAssist/ShaderLabTypingAssist.cs [106:213]


        private bool HandleEnterAction(IActionContext actionContext)
        {
            if (actionContext.EnsureWritable() != EnsureWritableResult.SUCCESS)
                return false;
            if (ShouldIgnoreCaretPosition(actionContext.TextControl, out var cachingLexer)) 
                return false;
            
            var textControl = actionContext.TextControl;
            if (GetTypingAssistOption(textControl, TypingAssistOptions.SmartIndentOnEnterExpression))
            {
                using (CommandProcessor.UsingCommand("Smart Enter"))
                {
                    if (textControl.Selection.OneDocRangeWithCaret().Length > 0)
                        return false;

                    var offset = textControl.Caret.Offset();
                    if (offset == 0)
                        return false;
                    
                    var rangeStart = offset;
                    var rangeEnd = offset;
                    var isInsideNonWhitespaceToken = cachingLexer.TokenType is { IsWhitespace: false } &&
                                                     cachingLexer.TokenStart < offset &&
                                                     cachingLexer.TokenEnd > offset;
                    // no need to search for whitespaces if we are inside a non-whitespace token
                    if (!isInsideNonWhitespaceToken)
                    {
                        // Remove whitespaces after end of preceding non-whitespace token
                        if (MoveToClosestTokenNodeTypeSkippingWhitespaces(cachingLexer, -1) is { IsWhitespace: false })
                            rangeStart = cachingLexer.TokenEnd;
                        cachingLexer.Advance();

                        while (cachingLexer.TokenType is { IsWhitespace: true } && cachingLexer.TokenType != ShaderLabTokenType.NEW_LINE)
                            cachingLexer.Advance();
                        rangeEnd = cachingLexer.TokenStart;
                    }

                    var isStartOfBlock = cachingLexer.TokenType == ShaderLabTokenType.LBRACE;
                    var isEndOfBlock = cachingLexer.TokenType == ShaderLabTokenType.RBRACE;
                    if (!cachingLexer.FindTokenAt(offset - 1))
                        return false;
                    
                    // move to either to start of block or closest command keyword, if next symbol is end of block then only start of block is a valid reference
                    if (!MoveLexerToIdentReference(cachingLexer, !isEndOfBlock)) 
                        return false;

                    // should only append block indent if '{' is a first indentation reference, if there preceding shader command then just use same indentation.
                    // If next token is end of block then it also shouldn't be indented inside of block 
                    var stoppedAtStartOfBlock = cachingLexer.TokenType == ShaderLabTokenType.LBRACE;
                    var document = textControl.Document;
                    // e.g  
                    //Shader "Custom/Test2_hlsl" {
                    //<caret>    Properties {

                    //<caret>{

                    //<caret>    {
                    if (!TryGetLineIndent(cachingLexer, document, out var lineIndent))
                        return false;
                    var formattingService = GetFormatSettingsService(textControl);
                    var braceStyle = (formattingService as ShaderLabFormatSettingsKey)?.BraceStyle ?? BraceFormatStyle.NEXT_LINE;
                    var shouldBeShifted = braceStyle is BraceFormatStyle.NEXT_LINE_SHIFTED or BraceFormatStyle.NEXT_LINE_SHIFTED_2;
                    var shouldAppendBlockIndent = isStartOfBlock && shouldBeShifted || stoppedAtStartOfBlock && braceStyle != BraceFormatStyle.NEXT_LINE_SHIFTED;
                    var indent = lineIndent;
                    if (shouldAppendBlockIndent)
                        indent += formattingService.GetIndentStr();
                    string? prologIndent = null;
                    // if Enter pressed before end of block then we want to insert extra empty line inside of the block
                    string? epilogueIndent = null;
                    if (isEndOfBlock && (stoppedAtStartOfBlock || MoveLexerToIdentReference(cachingLexer, false) && TryGetLineIndent(cachingLexer, document, out lineIndent)))
                    {
                        epilogueIndent = lineIndent;
                        // if Enter pressed inside of empty braces on same line and these are not on own line yet then insert line before opening brace for next line brace style
                        if (braceStyle is BraceFormatStyle.NEXT_LINE or BraceFormatStyle.NEXT_LINE_SHIFTED or BraceFormatStyle.NEXT_LINE_SHIFTED_2
                            && GetClosestTokenNodeTypeSkippingWhitespaces(cachingLexer, 1) == ShaderLabTokenType.RBRACE
                            && MoveToClosestTokenNodeTypeSkippingWhitespaces(cachingLexer, -1) is { IsWhitespace: false })
                        {
                            rangeStart = cachingLexer.TokenEnd;
                            if (shouldBeShifted)
                            {
                                var indentStr = formattingService.GetIndentStr();
                                indent += indentStr;
                                epilogueIndent += indentStr;
                            }
                            prologIndent = epilogueIndent;
                        }
                    }

                    CommitPsiOnlyAndProceedWithDirtyCaches(textControl, _ =>
                    {
                        var newLine = GetNewLineText(textControl.Document.GetPsiSourceFile(Solution));
                        var sb = new StringBuilder();
                        if (prologIndent != null)
                            sb.Append(newLine).Append(prologIndent).Append(ShaderLabTokenType.LBRACE.TokenRepresentation);
                        sb.Append(newLine).Append(indent);
                        var caretOffset = sb.Length;
                        if (epilogueIndent != null)
                            sb.Append(newLine).Append(epilogueIndent);
                        var range = new TextRange(rangeStart, rangeEnd);
                        document.ReplaceText(range, sb.ToString());
                        textControl.Caret.MoveTo(range.StartDocOffset() + caretOffset, CaretVisualPlacement.DontScrollIfVisible);
                    });
                    return true;
                }
            }

            return false;
        }