Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Editor: show a diff in base like as if I would compare one side to base #160292

Closed
hediet opened this issue Sep 7, 2022 · 7 comments
Closed
Assignees
Labels
feature-request Request for new features or functionality merge-editor verification-needed Verification of issue is requested verified Verification succeeded
Milestone

Comments

@hediet
Copy link
Member

hediet commented Sep 7, 2022

once base is visible, can we not show a diff like as if I would compare one side to base? Maybe take the active focussed side and update diff markers?

here is what I see today in diff and that helps me to understand the reasons for a change:

image

Originally posted by @bpasero in #160247 (comment)

Verification steps:

  • Open this merge conflict using the merge open from json command (F1):
{
    "languageId": "typescript",
    "base": "        function nextTokenIsIdentifierOrKeywordOnSameLine() {\r\n            nextToken();\r\n            return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();\r\n        }\r\n\r\n        function parseStatement(): Statement {\r\n            switch (token) {\r\n                case SyntaxKind.OpenBraceToken:\r\n                    return parseBlock(SyntaxKind.Block, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false);\r\n                case SyntaxKind.VarKeyword:\r\n                case SyntaxKind.ConstKeyword:\r\n                    // const here should always be parsed as const declaration because of check in 'isStatement' \r\n                    return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.FunctionKeyword:\r\n                    return parseFunctionDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.SemicolonToken:\r\n                    return parseEmptyStatement();\r\n                case SyntaxKind.IfKeyword:\r\n                    return parseIfStatement();\r\n                case SyntaxKind.DoKeyword:\r\n                    return parseDoStatement();\r\n                case SyntaxKind.WhileKeyword:\r\n                    return parseWhileStatement();\r\n                case SyntaxKind.ForKeyword:\r\n                    return parseForOrForInStatement();\r\n                case SyntaxKind.ContinueKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);\r\n                case SyntaxKind.BreakKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);\r\n                case SyntaxKind.ReturnKeyword:\r\n                    return parseReturnStatement();\r\n                case SyntaxKind.WithKeyword:\r\n                    return parseWithStatement();\r\n                case SyntaxKind.SwitchKeyword:\r\n                    return parseSwitchStatement();\r\n                case SyntaxKind.ThrowKeyword:\r\n                    return parseThrowStatement();\r\n                case SyntaxKind.TryKeyword:\r\n                // Include the next two for error recovery.\r\n                case SyntaxKind.CatchKeyword:\r\n                case SyntaxKind.FinallyKeyword:\r\n                    return parseTryStatement();\r\n                case SyntaxKind.DebuggerKeyword:\r\n                    return parseDebuggerStatement();\r\n                case SyntaxKind.LetKeyword:\r\n                    // If let follows identifier on the same line, it is declaration parse it as variable statement\r\n                    if (isLetDeclaration()) {\r\n                        return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                    }\r\n                    // Else parse it like identifier - fall through\r\n                default:\r\n                    return isLabel()\r\n                        ? parseLabeledStatement()\r\n                        : parseExpressionStatement();\r\n            }\r\n        }\r\n\r\n        function parseFunctionBlockOrSemicolon(isGenerator: boolean): Block {\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false);\r\n            }\r\n\r\n            parseSemicolon(Diagnostics.or_expected);\r\n            return undefined;\r\n        }\r\n\r\n        // DECLARATIONS\r\n\r\n        function parseBindingElement(context: ParsingContext): BindingElement {\r\n            if (context === ParsingContext.ArrayBindingElements && token === SyntaxKind.CommaToken) {\r\n                return <BindingElement>createNode(SyntaxKind.OmittedExpression);\r\n            }\r\n            var node = <BindingElement>createNode(SyntaxKind.BindingElement);\r\n            if (context === ParsingContext.ObjectBindingElements) {\r\n                // TODO(andersh): Handle computed properties\r\n                var id = parsePropertyName();\r\n                if (id.kind === SyntaxKind.Identifier && token !== SyntaxKind.ColonToken) {\r\n                    node.name = <Identifier>id;\r\n                }\r\n                else {\r\n                    parseExpected(SyntaxKind.ColonToken);\r\n                    node.propertyName = <Identifier>id;\r\n                    node.name = parseIdentifierOrPattern();\r\n                }\r\n            }\r\n            else {\r\n                node.name = parseIdentifierOrPattern();\r\n            }\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseBindingList(context: ParsingContext): NodeArray<BindingElement> {\r\n            return parseDelimitedList(context, () => parseBindingElement(context));\r\n        }\r\n\r\n        function parseObjectBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBraceToken);\r\n            node.elements = parseBindingList(ParsingContext.ObjectBindingElements);\r\n            parseExpected(SyntaxKind.CloseBraceToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseArrayBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBracketToken);\r\n            node.elements = parseBindingList(ParsingContext.ArrayBindingElements);\r\n            parseExpected(SyntaxKind.CloseBracketToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function isIdentifierOrPattern() {\r\n            return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken || isIdentifier();\r\n        }\r\n\r\n        function parseIdentifierOrPattern(): Identifier | BindingPattern {\r\n            if (token === SyntaxKind.OpenBracketToken) {\r\n                return parseArrayBindingPattern();\r\n            }\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseObjectBindingPattern();\r\n            }\r\n            return parseIdentifier();\r\n        }\r\n\r\n        function parseVariableDeclaration(): VariableDeclaration {\r\n            var node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);\r\n            node.name = parseIdentifierOrPattern();\r\n            node.type = parseTypeAnnotation();\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function setFlag(nodes: NodeArray<VariableDeclaration>, flag: NodeFlags): NodeArray<VariableDeclaration> {\r\n            for (var i = 0; i < nodes.length; i++) {\r\n                var node = nodes[i];\r\n                node.flags |= flag;\r\n                if (node.name && isBindingPattern(node.name)) {\r\n                    setFlag((<BindingPattern>node.name).elements, flag);\r\n                }\r\n            }\r\n            return nodes;\r\n        }",
    "input1": "        function nextTokenIsIdentifierOrKeywordOnSameLine() {\r\n            nextToken();\r\n            return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();\r\n        }\r\n\r\n        function parseStatement(): Statement {\r\n            switch (token) {\r\n                case SyntaxKind.OpenBraceToken:\r\n                    return parseBlock(SyntaxKind.Block, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false);\r\n                case SyntaxKind.VarKeyword:\r\n                case SyntaxKind.ConstKeyword:\r\n                    // const here should always be parsed as const declaration because of check in 'isStatement' \r\n                    return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.FunctionKeyword:\r\n                    return parseFunctionDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.SemicolonToken:\r\n                    return parseEmptyStatement();\r\n                case SyntaxKind.IfKeyword:\r\n                    return parseIfStatement();\r\n                case SyntaxKind.DoKeyword:\r\n                    return parseDoStatement();\r\n                case SyntaxKind.WhileKeyword:\r\n                    return parseWhileStatement();\r\n                case SyntaxKind.ForKeyword:\r\n                    return parseForOrForInStatement();\r\n                case SyntaxKind.ContinueKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);\r\n                case SyntaxKind.BreakKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);\r\n                case SyntaxKind.ReturnKeyword:\r\n                    return parseReturnStatement();\r\n                case SyntaxKind.WithKeyword:\r\n                    return parseWithStatement();\r\n                case SyntaxKind.SwitchKeyword:\r\n                    return parseSwitchStatement();\r\n                case SyntaxKind.ThrowKeyword:\r\n                    return parseThrowStatement();\r\n                case SyntaxKind.TryKeyword:\r\n                // Include the next two for error recovery.\r\n                case SyntaxKind.CatchKeyword:\r\n                case SyntaxKind.FinallyKeyword:\r\n                    return parseTryStatement();\r\n                case SyntaxKind.DebuggerKeyword:\r\n                    return parseDebuggerStatement();\r\n                case SyntaxKind.LetKeyword:\r\n                    // If let follows identifier on the same line, it is declaration parse it as variable statement\r\n                    if (isLetDeclaration()) {\r\n                        return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                    }\r\n                    // Else parse it like identifier - fall through\r\n                default:\r\n                    return isLabel()\r\n                        ? parseLabeledStatement()\r\n                        : parseExpressionStatement();\r\n            }\r\n        }\r\n\r\n        function parseFunctionBlockOrSemicolon(isGenerator: boolean): Block {\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false);\r\n            }\r\n\r\n            parseSemicolon(Diagnostics.or_expected);\r\n            return undefined;\r\n        }\r\n\r\n        // DECLARATIONS\r\n\r\n        function parseBindingElement(context: ParsingContext): BindingElement {\r\n            if (context === ParsingContext.ArrayBindingElements && token === SyntaxKind.CommaToken) {\r\n                return <BindingElement>createNode(SyntaxKind.OmittedExpression);\r\n            }\r\n            var node = <BindingElement>createNode(SyntaxKind.BindingElement);\r\n            if (context === ParsingContext.ObjectBindingElements) {\r\n                // TODO(andersh): Handle computed properties\r\n                var id = parsePropertyName();\r\n                if (id.kind === SyntaxKind.Identifier && token !== SyntaxKind.ColonToken) {\r\n                    node.name = <Identifier>id;\r\n                }\r\n                else {\r\n                    parseExpected(SyntaxKind.ColonToken);\r\n                    node.propertyName = <Identifier>id;\r\n                    node.name = parseIdentifierOrPattern();\r\n                }\r\n            }\r\n            else {\r\n                node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);\r\n                node.name = parseIdentifierOrPattern();\r\n            }\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseBindingList(context: ParsingContext): NodeArray<BindingElement> {\r\n            return parseDelimitedList(context, () => parseBindingElement(context));\r\n        }\r\n\r\n        function parseObjectBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBraceToken);\r\n            node.elements = parseBindingList(ParsingContext.ObjectBindingElements);\r\n            parseExpected(SyntaxKind.CloseBraceToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseArrayBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBracketToken);\r\n            node.elements = parseBindingList(ParsingContext.ArrayBindingElements);\r\n            parseExpected(SyntaxKind.CloseBracketToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function isIdentifierOrPattern() {\r\n            return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken || isIdentifier();\r\n        }\r\n\r\n        function parseIdentifierOrPattern(): Identifier | BindingPattern {\r\n            if (token === SyntaxKind.OpenBracketToken) {\r\n                return parseArrayBindingPattern();\r\n            }\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseObjectBindingPattern();\r\n            }\r\n            return parseIdentifier();\r\n        }\r\n\r\n        function parseVariableDeclaration(): VariableDeclaration {\r\n            var node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);\r\n            node.name = parseIdentifierOrPattern();\r\n            node.type = parseTypeAnnotation();\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function setFlag(nodes: NodeArray<VariableDeclaration>, flag: NodeFlags): NodeArray<VariableDeclaration> {\r\n            for (var i = 0; i < nodes.length; i++) {\r\n                var node = nodes[i];\r\n                node.flags |= flag;\r\n                if (node.name && isBindingPattern(node.name)) {\r\n                    setFlag((<BindingPattern>node.name).elements, flag);\r\n                }\r\n            }\r\n            return nodes;\r\n        }",
    "input2": "        function nextTokenIsIdentifierOrKeywordOnSameLine() {\r\n            nextToken();\r\n            return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();\r\n        }\r\n\r\n        function parseStatement(): Statement {\r\n            switch (token) {\r\n                case SyntaxKind.OpenBraceToken:\r\n                    return parseBlock(SyntaxKind.Block, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false);\r\n                case SyntaxKind.VarKeyword:\r\n                case SyntaxKind.ConstKeyword:\r\n                    // const here should always be parsed as const declaration because of check in 'isStatement' \r\n                    return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.FunctionKeyword:\r\n                    return parseFunctionDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.SemicolonToken:\r\n                    return parseEmptyStatement();\r\n                case SyntaxKind.IfKeyword:\r\n                    return parseIfStatement();\r\n                case SyntaxKind.DoKeyword:\r\n                    return parseDoStatement();\r\n                case SyntaxKind.WhileKeyword:\r\n                    return parseWhileStatement();\r\n                case SyntaxKind.ForKeyword:\r\n                    return parseForOrForInStatement();\r\n                case SyntaxKind.ContinueKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);\r\n                case SyntaxKind.BreakKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);\r\n                case SyntaxKind.ReturnKeyword:\r\n                    return parseReturnStatement();\r\n                case SyntaxKind.WithKeyword:\r\n                    return parseWithStatement();\r\n                case SyntaxKind.SwitchKeyword:\r\n                    return parseSwitchStatement();\r\n                case SyntaxKind.ThrowKeyword:\r\n                    return parseThrowStatement();\r\n                case SyntaxKind.TryKeyword:\r\n                // Include the next two for error recovery.\r\n                case SyntaxKind.CatchKeyword:\r\n                case SyntaxKind.FinallyKeyword:\r\n                    return parseTryStatement();\r\n                case SyntaxKind.DebuggerKeyword:\r\n                    return parseDebuggerStatement();\r\n                case SyntaxKind.LetKeyword:\r\n                    // If let follows identifier on the same line, it is declaration parse it as variable statement\r\n                    if (isLetDeclaration()) {\r\n                        return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                    }\r\n                    // Else parse it like identifier - fall through\r\n                default:\r\n                    return parseExpressionOrLabeledStatement();\r\n            }\r\n        }\r\n\r\n        function parseFunctionBlockOrSemicolon(isGenerator: boolean): Block {\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false);\r\n            }\r\n\r\n            parseSemicolon(Diagnostics.or_expected);\r\n            return undefined;\r\n        }\r\n\r\n        // DECLARATIONS\r\n\r\n        function parseArrayBindingElement(): BindingElement {\r\n            if (token === SyntaxKind.CommaToken) {\r\n                return <BindingElement>createNode(SyntaxKind.OmittedExpression);\r\n            }\r\n\r\n            var node = <BindingElement>createNode(SyntaxKind.BindingElement);\r\n            node.name = parseIdentifierOrPattern();\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseObjectBindingElement(): BindingElement {\r\n            var node = <BindingElement>createNode(SyntaxKind.BindingElement);\r\n\r\n            // TODO(andersh): Handle computed properties\r\n            var id = parsePropertyName();\r\n            if (id.kind === SyntaxKind.Identifier && token !== SyntaxKind.ColonToken) {\r\n                node.name = <Identifier>id;\r\n            }\r\n            else {\r\n                parseExpected(SyntaxKind.ColonToken);\r\n                node.propertyName = <Identifier>id;\r\n                node.name = parseIdentifierOrPattern();\r\n            }\r\n\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseObjectBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBraceToken);\r\n            node.elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement);\r\n            parseExpected(SyntaxKind.CloseBraceToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseArrayBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBracketToken);\r\n            node.elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement);\r\n            parseExpected(SyntaxKind.CloseBracketToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function isIdentifierOrPattern() {\r\n            return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken || isIdentifier();\r\n        }\r\n\r\n        function parseIdentifierOrPattern(): Identifier | BindingPattern {\r\n            if (token === SyntaxKind.OpenBracketToken) {\r\n                return parseArrayBindingPattern();\r\n            }\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseObjectBindingPattern();\r\n            }\r\n            return parseIdentifier();\r\n        }\r\n\r\n        function parseVariableDeclaration(): VariableDeclaration {\r\n            var node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);\r\n            node.name = parseIdentifierOrPattern();\r\n            node.type = parseTypeAnnotation();\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function setFlag(nodes: NodeArray<VariableDeclaration>, flag: NodeFlags): NodeArray<VariableDeclaration> {\r\n            for (var i = 0; i < nodes.length; i++) {\r\n                var node = nodes[i];\r\n                node.flags |= flag;\r\n                if (node.name && isBindingPattern(node.name)) {\r\n                    setFlag((<BindingPattern>node.name).elements, flag);\r\n                }\r\n            }\r\n            return nodes;\r\n        }",
    "result": "        function nextTokenIsIdentifierOrKeywordOnSameLine() {\r\n            nextToken();\r\n            return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();\r\n        }\r\n\r\n        function parseStatement(): Statement {\r\n            switch (token) {\r\n                case SyntaxKind.OpenBraceToken:\r\n                    return parseBlock(SyntaxKind.Block, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false);\r\n                case SyntaxKind.VarKeyword:\r\n                case SyntaxKind.ConstKeyword:\r\n                    // const here should always be parsed as const declaration because of check in 'isStatement' \r\n                    return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.FunctionKeyword:\r\n                    return parseFunctionDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.SemicolonToken:\r\n                    return parseEmptyStatement();\r\n                case SyntaxKind.IfKeyword:\r\n                    return parseIfStatement();\r\n                case SyntaxKind.DoKeyword:\r\n                    return parseDoStatement();\r\n                case SyntaxKind.WhileKeyword:\r\n                    return parseWhileStatement();\r\n                case SyntaxKind.ForKeyword:\r\n                    return parseForOrForInStatement();\r\n                case SyntaxKind.ContinueKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);\r\n                case SyntaxKind.BreakKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);\r\n                case SyntaxKind.ReturnKeyword:\r\n                    return parseReturnStatement();\r\n                case SyntaxKind.WithKeyword:\r\n                    return parseWithStatement();\r\n                case SyntaxKind.SwitchKeyword:\r\n                    return parseSwitchStatement();\r\n                case SyntaxKind.ThrowKeyword:\r\n                    return parseThrowStatement();\r\n                case SyntaxKind.TryKeyword:\r\n                // Include the next two for error recovery.\r\n                case SyntaxKind.CatchKeyword:\r\n                case SyntaxKind.FinallyKeyword:\r\n                    return parseTryStatement();\r\n                case SyntaxKind.DebuggerKeyword:\r\n                    return parseDebuggerStatement();\r\n                case SyntaxKind.LetKeyword:\r\n                    // If let follows identifier on the same line, it is declaration parse it as variable statement\r\n                    if (isLetDeclaration()) {\r\n                        return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                    }\r\n                    // Else parse it like identifier - fall through\r\n                default:\r\n                    return parseExpressionOrLabeledStatement();\r\n            }\r\n        }\r\n\r\n        function parseFunctionBlockOrSemicolon(isGenerator: boolean): Block {\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false);\r\n            }\r\n\r\n            parseSemicolon(Diagnostics.or_expected);\r\n            return undefined;\r\n        }\r\n\r\n        // DECLARATIONS\r\n\r\n        function parseArrayBindingElement(): BindingElement {\r\n            if (token === SyntaxKind.CommaToken) {\r\n                return <BindingElement>createNode(SyntaxKind.OmittedExpression);\r\n            }\r\n\r\n            var node = <BindingElement>createNode(SyntaxKind.BindingElement);\r\n            if (context === ParsingContext.ObjectBindingElements) {\r\n                // TODO(andersh): Handle computed properties\r\n                var id = parsePropertyName();\r\n                if (id.kind === SyntaxKind.Identifier && token !== SyntaxKind.ColonToken) {\r\n                    node.name = <Identifier>id;\r\n                }\r\n                else {\r\n                    parseExpected(SyntaxKind.ColonToken);\r\n                    node.propertyName = <Identifier>id;\r\n                    node.name = parseIdentifierOrPattern();\r\n                }\r\n            }\r\n            else {\r\n                node.name = parseIdentifierOrPattern();\r\n            }\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseObjectBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBraceToken);\r\n            node.elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement);\r\n            parseExpected(SyntaxKind.CloseBraceToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseArrayBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBracketToken);\r\n            node.elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement);\r\n            parseExpected(SyntaxKind.CloseBracketToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function isIdentifierOrPattern() {\r\n            return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken || isIdentifier();\r\n        }\r\n\r\n        function parseIdentifierOrPattern(): Identifier | BindingPattern {\r\n            if (token === SyntaxKind.OpenBracketToken) {\r\n                return parseArrayBindingPattern();\r\n            }\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseObjectBindingPattern();\r\n            }\r\n            return parseIdentifier();\r\n        }\r\n\r\n        function parseVariableDeclaration(): VariableDeclaration {\r\n            var node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);\r\n            node.name = parseIdentifierOrPattern();\r\n            node.type = parseTypeAnnotation();\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function setFlag(nodes: NodeArray<VariableDeclaration>, flag: NodeFlags): NodeArray<VariableDeclaration> {\r\n            for (var i = 0; i < nodes.length; i++) {\r\n                var node = nodes[i];\r\n                node.flags |= flag;\r\n                if (node.name && isBindingPattern(node.name)) {\r\n                    setFlag((<BindingPattern>node.name).elements, flag);\r\n                }\r\n            }\r\n            return nodes;\r\n        }",
    "initialResult": "        function nextTokenIsIdentifierOrKeywordOnSameLine() {\r\n            nextToken();\r\n            return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak();\r\n        }\r\n\r\n        function parseStatement(): Statement {\r\n            switch (token) {\r\n                case SyntaxKind.OpenBraceToken:\r\n                    return parseBlock(SyntaxKind.Block, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false);\r\n                case SyntaxKind.VarKeyword:\r\n                case SyntaxKind.ConstKeyword:\r\n                    // const here should always be parsed as const declaration because of check in 'isStatement' \r\n                    return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.FunctionKeyword:\r\n                    return parseFunctionDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                case SyntaxKind.SemicolonToken:\r\n                    return parseEmptyStatement();\r\n                case SyntaxKind.IfKeyword:\r\n                    return parseIfStatement();\r\n                case SyntaxKind.DoKeyword:\r\n                    return parseDoStatement();\r\n                case SyntaxKind.WhileKeyword:\r\n                    return parseWhileStatement();\r\n                case SyntaxKind.ForKeyword:\r\n                    return parseForOrForInStatement();\r\n                case SyntaxKind.ContinueKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);\r\n                case SyntaxKind.BreakKeyword:\r\n                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);\r\n                case SyntaxKind.ReturnKeyword:\r\n                    return parseReturnStatement();\r\n                case SyntaxKind.WithKeyword:\r\n                    return parseWithStatement();\r\n                case SyntaxKind.SwitchKeyword:\r\n                    return parseSwitchStatement();\r\n                case SyntaxKind.ThrowKeyword:\r\n                    return parseThrowStatement();\r\n                case SyntaxKind.TryKeyword:\r\n                // Include the next two for error recovery.\r\n                case SyntaxKind.CatchKeyword:\r\n                case SyntaxKind.FinallyKeyword:\r\n                    return parseTryStatement();\r\n                case SyntaxKind.DebuggerKeyword:\r\n                    return parseDebuggerStatement();\r\n                case SyntaxKind.LetKeyword:\r\n                    // If let follows identifier on the same line, it is declaration parse it as variable statement\r\n                    if (isLetDeclaration()) {\r\n                        return parseVariableStatement(scanner.getStartPos(), /*modifiers:*/ undefined);\r\n                    }\r\n                    // Else parse it like identifier - fall through\r\n                default:\r\n                    return parseExpressionOrLabeledStatement();\r\n            }\r\n        }\r\n\r\n        function parseFunctionBlockOrSemicolon(isGenerator: boolean): Block {\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false);\r\n            }\r\n\r\n            parseSemicolon(Diagnostics.or_expected);\r\n            return undefined;\r\n        }\r\n\r\n        // DECLARATIONS\r\n\r\n        function parseArrayBindingElement(): BindingElement {\r\n            if (token === SyntaxKind.CommaToken) {\r\n                return <BindingElement>createNode(SyntaxKind.OmittedExpression);\r\n            }\r\n\r\n            var node = <BindingElement>createNode(SyntaxKind.BindingElement);\r\n            if (context === ParsingContext.ObjectBindingElements) {\r\n                // TODO(andersh): Handle computed properties\r\n                var id = parsePropertyName();\r\n                if (id.kind === SyntaxKind.Identifier && token !== SyntaxKind.ColonToken) {\r\n                    node.name = <Identifier>id;\r\n                }\r\n                else {\r\n                    parseExpected(SyntaxKind.ColonToken);\r\n                    node.propertyName = <Identifier>id;\r\n                    node.name = parseIdentifierOrPattern();\r\n                }\r\n            }\r\n            else {\r\n                node.name = parseIdentifierOrPattern();\r\n            }\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseObjectBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ObjectBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBraceToken);\r\n            node.elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement);\r\n            parseExpected(SyntaxKind.CloseBraceToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function parseArrayBindingPattern(): BindingPattern {\r\n            var node = <BindingPattern>createNode(SyntaxKind.ArrayBindingPattern);\r\n            parseExpected(SyntaxKind.OpenBracketToken);\r\n            node.elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement);\r\n            parseExpected(SyntaxKind.CloseBracketToken);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function isIdentifierOrPattern() {\r\n            return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.OpenBracketToken || isIdentifier();\r\n        }\r\n\r\n        function parseIdentifierOrPattern(): Identifier | BindingPattern {\r\n            if (token === SyntaxKind.OpenBracketToken) {\r\n                return parseArrayBindingPattern();\r\n            }\r\n            if (token === SyntaxKind.OpenBraceToken) {\r\n                return parseObjectBindingPattern();\r\n            }\r\n            return parseIdentifier();\r\n        }\r\n\r\n        function parseVariableDeclaration(): VariableDeclaration {\r\n            var node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration);\r\n            node.name = parseIdentifierOrPattern();\r\n            node.type = parseTypeAnnotation();\r\n            node.initializer = parseInitializer(/*inParameter*/ false);\r\n            return finishNode(node);\r\n        }\r\n\r\n        function setFlag(nodes: NodeArray<VariableDeclaration>, flag: NodeFlags): NodeArray<VariableDeclaration> {\r\n            for (var i = 0; i < nodes.length; i++) {\r\n                var node = nodes[i];\r\n                node.flags |= flag;\r\n                if (node.name && isBindingPattern(node.name)) {\r\n                    setFlag((<BindingPattern>node.name).elements, flag);\r\n                }\r\n            }\r\n            return nodes;\r\n        }"
}
  • Open base view in the menu behind "..."
  • Focus yours or theirs and verify base shows diffs against the selected editor.
@hediet hediet added feature-request Request for new features or functionality merge-editor labels Sep 7, 2022
@hediet hediet modified the milestones: On Deck, September 2022 Sep 7, 2022
@hediet hediet self-assigned this Sep 7, 2022
@bpasero
Copy link
Member

bpasero commented Sep 7, 2022

👍 , I think the interesting bit is that the diff would show for the active side (Incoming, Current) because I think we cannot really show a meaningful diff of 3 editors compared to each other?

@bpasero
Copy link
Member

bpasero commented Sep 7, 2022

Oh and it would probably require Base to be in between Incoming and Current

@hediet
Copy link
Member Author

hediet commented Sep 7, 2022

I think we cannot really show a meaningful diff of 3 editors compared to each other?

Not really I think.

I like this idea!

@alexdima
Copy link
Member

alexdima commented Oct 7, 2022

When rendering decorations in Base (based on which other editor is focused), it would be good to improve the focus indication for code editors. Otherwise it would be confusing to realise what Base is diffed against when alt-tabbing and returning after a few minutes.

@hediet
Copy link
Member Author

hediet commented Oct 13, 2022

Closed in #163553

@hediet hediet closed this as completed Oct 13, 2022
@hediet hediet added the verification-needed Verification of issue is requested label Oct 25, 2022
@rzhao271 rzhao271 added the verified Verification succeeded label Oct 25, 2022
@rzhao271
Copy link
Contributor

Does the diff only show the part most relevant to the merge conflict?
In the screenshot below, base has a function parseBindingElement, which seems to be renamed to parseArrayBindingElement in Input 2, but the diff isn't highlighted for those lines.
Demo of issue

@hediet
Copy link
Member Author

hediet commented Oct 26, 2022

The diff is only shown for proper conflicts. You can show all conflicts through the ... menu.

@github-actions github-actions bot locked and limited conversation to collaborators Nov 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature-request Request for new features or functionality merge-editor verification-needed Verification of issue is requested verified Verification succeeded
Projects
None yet
Development

No branches or pull requests

4 participants