prettier / plugin-python

Prettier Python Plugin
MIT License
517 stars 41 forks source link

Crash with inline comment in assign expression #81

Closed cosmith closed 6 years ago

cosmith commented 6 years ago

I tried running prettier on some of my code and ran into a crash.

Minimal repro code:

message = (
    "hello {}"  # comment
).format("world")

Stacktrace:

[error] test.py: Error: Comment location overlaps with node location
[error]     at decorateComment (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:119:11)
[error]     at decorateComment (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:94:7)
[error]     at decorateComment (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:94:7)
[error]     at decorateComment (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:94:7)
[error]     at comments.forEach (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:168:5)
[error]     at Array.forEach (<anonymous>)
[error]     at Object.attach (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/main/comments.js:160:12)
[error]     at attachComments (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/index.js:34:14)
[error]     at formatWithCursor (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/index.js:120:23)
[error]     at Object.formatWithCursor (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/index.js:402:12)
[error]     at format (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:157:19)
[error]     at eachFilename (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:380:16)
[error]     at filePaths.forEach.filePath (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:322:7)
[error]     at Array.forEach (<anonymous>)
[error]     at eachFilename (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:321:15)
[error]     at Object.formatFiles (/Users/corentinsmith/projects/plugin-python/node_modules/prettier/src/cli/util.js:338:3)
error Command failed with exit code 2.

The same construct in JS works fine:

IN:

var message = (
    "hello {}"  // comment
).format("world")

OUT:

var message = "hello {}" // comment
  .format("world");

I have no experience with the prettier codebase but I'm interested in trying to fix this. I think something is missing from the AST, I printed both JS and Python to try to spot the difference:

JS AST

``` { "type": "File", "start": 0, "end": 61, "loc": { "start": { "line": 1, "column": 0 }, "end": { "line": 4, "column": 0 } }, "program": { "type": "Program", "start": 0, "end": 61, "loc": { "start": { "line": 1, "column": 0 }, "end": { "line": 4, "column": 0 } }, "sourceType": "module", "body": [ { "type": "VariableDeclaration", "start": 0, "end": 60, "loc": { "start": { "line": 1, "column": 0 }, "end": { "line": 3, "column": 17 } }, "declarations": [ { "type": "VariableDeclarator", "start": 4, "end": 60, "loc": { "start": { "line": 1, "column": 4 }, "end": { "line": 3, "column": 17 } }, "id": { "type": "Identifier", "start": 4, "end": 11, "loc": { "start": { "line": 1, "column": 4 }, "end": { "line": 1, "column": 11 }, "identifierName": "message" }, "name": "message" }, "init": { "type": "CallExpression", "start": 14, "end": 60, "loc": { "start": { "line": 1, "column": 14 }, "end": { "line": 3, "column": 17 } }, "callee": { "type": "MemberExpression", "start": 14, "end": 51, "loc": { "start": { "line": 1, "column": 14 }, "end": { "line": 3, "column": 8 } }, "object": { "type": "StringLiteral", "start": 20, "end": 30, "loc": { "start": { "line": 2, "column": 4 }, "end": { "line": 2, "column": 14 } }, "extra": { "rawValue": "hello {}", "raw": "\"hello {}\"", "parenthesized": true, "parenStart": 14 }, "value": "hello {}", "leadingComments": null, "trailingComments": [ { "type": "CommentLine", "value": " comment", "start": 32, "end": 42, "loc": { "start": { "line": 2, "column": 16 }, "end": { "line": 2, "column": 26 } } } ] }, "property": { "type": "Identifier", "start": 45, "end": 51, "loc": { "start": { "line": 3, "column": 2 }, "end": { "line": 3, "column": 8 }, "identifierName": "format" }, "name": "format", "leadingComments": [ { "type": "CommentLine", "value": " comment", "start": 32, "end": 42, "loc": { "start": { "line": 2, "column": 16 }, "end": { "line": 2, "column": 26 } } } ] }, "computed": false }, "arguments": [ { "type": "StringLiteral", "start": 52, "end": 59, "loc": { "start": { "line": 3, "column": 9 }, "end": { "line": 3, "column": 16 } }, "extra": { "rawValue": "world", "raw": "\"world\"" }, "value": "world" } ] } } ], "kind": "var" } ], "directives": [] }, "comments": [ { "type": "CommentLine", "value": " comment", "start": 32, "end": 42, "loc": { "start": { "line": 2, "column": 16 }, "end": { "line": 2, "column": 26 } } } ] } ```

Python AST

``` { "ast_type": "Module", "body": [ { "ast_type": "Assign", "col_offset": 0, "end": 55, "lineno": 1, "source": "message = (\n \"hello {}\" # comment\n).format(\"world\")", "start": 0, "targets": [ { "ast_type": "Name", "col_offset": 0, "ctx": { "ast_type": "Store", "source": "" }, "end": 7, "id": "message", "lineno": 1, "source": "message", "start": 0 } ], "value": { "args": [ { "ast_type": "Str", "col_offset": 9, "end": 54, "lineno": 3, "s": "world", "source": "\"world\"", "start": 47 } ], "ast_type": "Call", "col_offset": 4, "end": 55, "func": { "ast_type": "Attribute", "attr": "format", "col_offset": 4, "ctx": { "ast_type": "Load", "source": "" }, "end": 46, "lineno": 2, "source": "(\n \"hello {}\" # comment\n).format", "start": 10, "value": { "ast_type": "Str", "col_offset": 4, "end": 26, "lineno": 2, "s": "hello {}", "source": "\"hello {}\"", "start": 16 } }, "keywords": [], "lineno": 2, "source": "(\n \"hello {}\" # comment\n).format(\"world\")", "start": 10 } } ], "comments": [ { "ast_type": "comment", "end": 37, "start": 28, "value": "# comment" } ], "end": 55, "source": "message = (\n \"hello {}\" # comment\n).format(\"world\")", "start": 0 } ```

Any pointers on where to start digging to get this fixed?

cosmith commented 6 years ago

Thanks!