Skip to content

Commit

Permalink
fix: handle missing case in CS node location fixing (#271)
Browse files Browse the repository at this point in the history
Fixes decaffeinate/decaffeinate#1177

In some cases, we need to extend the bounds of a function to include its
terminating semicolon, and propagate that extension up the AST. In the new test
case, there was a Value with no properties that wasn't having its bounds
extended properly, which confused decaffeinate later.

This fix broke another case due to heregex flags not being properly positioned,
so detect heregex flag literals and fix their location as well.
  • Loading branch information
alangpierce authored Oct 22, 2017
1 parent ffb5740 commit 2e667c3
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 2 deletions.
31 changes: 29 additions & 2 deletions src/util/fixLocations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Assign, Base, Block, Call, Class, Code, Extends, For, If, In, Index, Obj, Op, Param, Slice, Switch, Try, Value, While } from 'decaffeinate-coffeescript/lib/coffee-script/nodes';
import SourceType from 'coffee-lex/dist/SourceType';
import {
Assign, Base, Block, Call, Class, Code, Extends, For, If, In, Index, Literal,
Obj, Op, Param, Slice, Switch, Try, Value, While
} from 'decaffeinate-coffeescript/lib/coffee-script/nodes';
import fixInvalidLocationData from './fixInvalidLocationData';
import locationWithLastPosition from './locationWithLastPosition';
import mergeLocations from './mergeLocations';
Expand All @@ -17,7 +21,7 @@ export default function fixLocations(context: ParseContext, node: Base): void {
node.locationData = fixInvalidLocationData(node.locationData, context.linesAndColumns);

if (node instanceof Value) {
let lastChild = node.properties[node.properties.length - 1];
let lastChild = node.properties[node.properties.length - 1] || node.base;
if (lastChild) {
node.locationData = locationWithLastPosition(
node.locationData,
Expand Down Expand Up @@ -223,4 +227,27 @@ export default function fixLocations(context: ParseContext, node: Base): void {
lastChild.locationData
);
}

if (node instanceof Literal) {
// Heregexp flags have an incorrect location, so detect that case and adjust
// the end location to be correct.
let endIndex = linesAndColumns.indexForLocation({
line: node.locationData.last_line,
column: node.locationData.last_column
});
if (endIndex !== null) {
let tokenIndex = context.sourceTokens.indexOfTokenNearSourceIndex(endIndex);
let token = context.sourceTokens.tokenAtIndex(tokenIndex);
if (token && token.type === SourceType.HEREGEXP_END) {
let location = linesAndColumns.locationForIndex(token.end - 1);
if (location) {
node.locationData = {
...node.locationData,
last_line: location.line,
last_column: location.column,
};
}
}
}
}
}
3 changes: 3 additions & 0 deletions test/examples/nested-object-with-inner-semicolon/input.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
a:
b: ->
c;
103 changes: 103 additions & 0 deletions test/examples/nested-object-with-inner-semicolon/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
"body": {
"column": 1,
"end": 17,
"inline": false,
"line": 1,
"raw": "a:\n b: ->\n c;",
"start": 0,
"statements": [
{
"column": 1,
"end": 17,
"line": 1,
"members": [
{
"column": 1,
"end": 17,
"expression": {
"column": 3,
"end": 17,
"line": 2,
"members": [
{
"column": 3,
"end": 17,
"expression": {
"body": {
"column": 5,
"end": 17,
"inline": false,
"line": 3,
"raw": "c;",
"start": 15,
"statements": [
{
"column": 5,
"data": "c",
"end": 16,
"line": 3,
"raw": "c",
"start": 15,
"type": "Identifier"
}
],
"type": "Block"
},
"column": 6,
"end": 17,
"line": 2,
"parameters": [
],
"raw": "->\n c;",
"start": 8,
"type": "Function"
},
"key": {
"column": 3,
"data": "b",
"end": 6,
"line": 2,
"raw": "b",
"start": 5,
"type": "Identifier"
},
"line": 2,
"raw": "b: ->\n c;",
"start": 5,
"type": "ObjectInitialiserMember"
}
],
"raw": "b: ->\n c;",
"start": 5,
"type": "ObjectInitialiser"
},
"key": {
"column": 1,
"data": "a",
"end": 1,
"line": 1,
"raw": "a",
"start": 0,
"type": "Identifier"
},
"line": 1,
"raw": "a:\n b: ->\n c;",
"start": 0,
"type": "ObjectInitialiserMember"
}
],
"raw": "a:\n b: ->\n c;",
"start": 0,
"type": "ObjectInitialiser"
}
],
"type": "Block"
},
"column": 1,
"end": 18,
"line": 1,
"raw": "a:\n b: ->\n c;\n",
"start": 0,
"type": "Program"
}

0 comments on commit 2e667c3

Please sign in to comment.