styled-components / typescript-styled-plugin

TypeScript server plugin that adds intellisense to styled component css strings
MIT License
76 stars 7 forks source link

'identifier expected' error when using a string template followed by a pseudo-element selector #21

Open Codex- opened 11 months ago

Codex- commented 11 months ago

Repost of: https://github.com/styled-components/vscode-styled-components/issues/440

Reproduction when running the vscode extension:

const test = ''
const StyledDiv = styled.div`
  .${test}:before { // <- identifier expected (ts-styled-plugin(9999))
    border-bottom: none;
    transition: none;
  }
`

Screenshot of error: image

I've created a test case that reproduces this error in the e2e:

it('should not error with an interpolation identifier with a pseudo selector', async () => {
    const errorResponse = await getSemanticDiagnosticsForFile([
        "function css(...args){}",
        "const mixin = ''",
        "css`",
        "  .${mixin}:before {",
        "    border-bottom: none;",
        "    transition: none;",
        "  }",
        "`",
    ].join('\n'));
    assert.isTrue(errorResponse.success);
    assert.strictEqual(errorResponse.body.length, 0);
});

Error response:

[
  {
    start: { line: 4, offset: 4 },
    end: { line: 4, offset: 5 },
    text: 'identifier expected',
    code: 9999,
    category: 'error',
    source: 'ts-styled-plugin'
  }
]

So far this appears to be a bug in how getSubstitution selects which things to substitute

I've found some inconsistencies, the docstring states:

// if in-property, replace with "xxxxxx"
// if a mixin, replace with "      "

Various tests I've done, with the parts logged:

"  ${mixin}:before {", <--- no error

Info 94   [11:12:22.643] 
  ,&       ,:before {
    border-bottom: none;
    transition: none;
  }

"  .${mixin}:before {", <--- identifier expected error

Info 94   [11:13:06.229] 
  .,&       ,:before {
    border-bottom: none;
    transition: none;
  }

"  .${mixin} {", <--- no error

Info 92   [11:13:36.643] 
  .,xxxxxxxx, {
    border-bottom: none;
    transition: none;
  }

Weird that the last case gets xxxxxxxx while the others get spaces, shouldn't they all get one of the other?