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

Fix(transformer/elm): handle elm error properly without errors property #8319

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 43 additions & 0 deletions packages/core/integration-tests/test/elm.js
Expand Up @@ -133,4 +133,47 @@ describe('elm', function () {
},
);
});

it('should produce correct formatting and indentation when elm fails without errors property', async function () {
await assert.rejects(
() =>
bundle(path.join(__dirname, 'integration/elm-error/index.js'), {
mode: 'production',
}),

{
name: 'BuildError',
diagnostics: [
{
message:
'\n' +
'-- DEBUG REMNANTS ------------------------------------------------------------- \n' +
'\n' +
'There are uses of the `Debug` module in the following modules:\n' +
'\n' +
' **Main**\n' +
'\n' +
'But the --optimize flag only works if all `Debug` functions are removed!\n' +
'\n' +
'__Note__: The issue is that --optimize strips out info needed by `Debug` functions.\n' +
'Here are two examples:\n' +
'\n' +
' (1) It shortens record field names. This makes the generated JavaScript is\n' +
' smaller, but `Debug.toString` cannot know the real field names anymore.\n' +
'\n' +
' (2) Values like `type Height = Height Float` are unboxed. This reduces\n' +
' allocation, but it also means that `Debug.toString` cannot tell if it is\n' +
' looking at a `Height` or `Float` value.\n' +
'\n' +
'There are a few other cases like that, and it will be much worse once we start\n' +
'inlining code. That optimization could move `Debug.log` and `Debug.todo` calls,\n' +
'resulting in unpredictable behavior. I hope that clarifies why this restriction\n' +
'exists!',
origin: '@parcel/elm-transformer',
stack: '',
},
],
},
);
});
});
@@ -0,0 +1,24 @@
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0"
},
"indirect": {
"elm/json": "1.1.3",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.2"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}
@@ -0,0 +1,5 @@
var local = require('./src/Main.elm');

module.exports = function () {
return local;
};
@@ -0,0 +1 @@
{}
@@ -0,0 +1,49 @@
module Main exposing (main)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)


type alias Model =
{ count : Int }


initialModel : Model
initialModel =
{ count = 0 }


type Msg
= Increment
| Decrement


update : Msg -> Model -> Model
update msg model =
case msg of
Increment ->
Debug.log "incremented!!"
{ model | count = model.count + 1 }

Decrement ->
Debug.log "decremented!!"
{ model | count = model.count - 1 }


view : Model -> Html Msg
view model =
div []
[ button [ onClick Increment ] [ text "+1" ]
, div [] [ text <| String.fromInt model.count ]
, button [ onClick Decrement ] [ text "-1" ]
]


main : Program () Model Msg
main =
Browser.sandbox
{ init = initialModel
, view = view
, update = update
}
Empty file.
46 changes: 32 additions & 14 deletions packages/transformers/elm/src/ElmTransformer.js
Expand Up @@ -64,6 +64,20 @@ export default (new Transformer({
let compilerJson = e.message.split('\n')[1];
let compilerDiagnostics = JSON.parse(compilerJson);

// sometimes, `errors` property does not exist on the error object thrown by `compileToString` module.
// In such case, a content equal to `error.errors[num].problems[num]` is expanded.
// so this line handle such a case.
if (!compilerDiagnostics.errors) {
throw new ThrowableDiagnostic({
diagnostic: elmProblemToParcelDiagnostic(
compilerDiagnostics,
compilerDiagnostics.path
? path.relative(process.cwd(), compilerDiagnostics.path)
: '',
),
});
}

throw new ThrowableDiagnostic({
diagnostic: compilerDiagnostics.errors.flatMap(
elmErrorToParcelDiagnostics,
Expand Down Expand Up @@ -173,22 +187,26 @@ function formatMessagePiece(piece) {
return md`${piece}`;
}

function elmProblemToParcelDiagnostic(problem, relativePath) {
const padLength = 80 - 5 - problem.title.length - relativePath.length;
const dashes = '-'.repeat(padLength);
const message = [
'',
`-- ${problem.title} ${dashes} ${relativePath}`,
'',
problem.message.map(formatMessagePiece).join(''),
].join('\n');

return {
message,
origin: '@parcel/elm-transformer',
stack: '', // set stack to empty since it is not useful
};
}

function elmErrorToParcelDiagnostics(error) {
const relativePath = path.relative(process.cwd(), error.path);
return error.problems.map(problem => {
const padLength = 80 - 5 - problem.title.length - relativePath.length;
const dashes = '-'.repeat(padLength);
const message = [
'',
`-- ${problem.title} ${dashes} ${relativePath}`,
'',
problem.message.map(formatMessagePiece).join(''),
].join('\n');

return {
message,
origin: '@parcel/elm-transformer',
stack: '', // set stack to empty since it is not useful
};
return elmProblemToParcelDiagnostic(problem, relativePath);
});
}