francoismassart / eslint-plugin-tailwindcss

ESLint plugin for Tailwind CSS usage
https://www.npmjs.com/package/eslint-plugin-tailwindcss
MIT License
1.38k stars 65 forks source link

fix ast expression tests for null expressions #345

Closed kesor closed 1 month ago

kesor commented 1 month ago

Pull Request Name

Fix a TypeError exception for null expressions in the AST.

Description

While linting my application, exceptions about the AST are raised in some components:

TypeError: Cannot read properties of null (reading 'type') Occurred while linting /app/src/components/TestComponent.vue:47 Rule: "vue/attributes-order"
    at isArrayExpression (/app/node_modules/eslint-plugin-tailwindcss/lib/util/ast.js:99:92)
    at isVueValidAttributeValue (/app/node_modules/eslint-plugin-tailwindcss/lib/util/ast.js:121:10)
    at Object.isValidVueAttribute (/app/node_modules/eslint-plugin-tailwindcss/lib/util/ast.js:184:8)

Apparently the VExpressionContainer can pass all the checks, but the value for expression is null. This modification makes sure it is not treated as an object that can be passed onward.

Type of change

How Has This Been Tested?

Linting fails on some components in our big application, this change fixes the thrown exception.

Test Configuration:

francoismassart commented 1 month ago

@kesor could you provide an example of the failing AST parsing ?

Thank you

kesor commented 1 month ago

This is a bit hard to debug, but if I am not mistaken it would be this Vue.js element --

          <td
            class="text-end"
            :class="(marketValue ?? 0) < (totalCost ?? 0) ? 'text-danger' : 'text-success'"
          >
            {{ marketValue?.toFixed(2) }}
          </td>

Some debug logging that I patched the ast.js to print out include --

<ref *2> {                                                                                                                                                                                                                            
  type: 'VAttribute',                                                                                                                                                                                                                 
  range: [ 3690, 3769 ],                                                                                                                                                                                                              
  loc: { start: { line: 103, column: 12 }, end: { line: 103, column: 91 } },                                                                                                                                                          
  parent: <ref *1> {                                                                                                                                                                                                                  
    type: 'VStartTag',                                                                                                                                                                                                                
    range: [ 3645, 3781 ],                                                                                                                                                                                                            
    loc: { start: [Object], end: [Object] },                                                                                                                                                                                          
    parent: {                                                                                                                                                                                                                         
      type: 'VElement',                                                                                                                                                                                                               
      range: [Array],                                                                                                                                                                                                                 
      loc: [Object],                                                                                                                                                                                                                  
      parent: [Object],                                                                                                                                                                                                               
      name: 'td',                                                                                                                                                                                                                     
      rawName: 'td',                                                                                                                                                                                                                  
      namespace: 'http://www.w3.org/1999/xhtml',                                                                                                                                                                                      
      startTag: [Circular *1],                                                                                                                                                                                                        
      children: [Array],                                                                                                                                                                                                              
      endTag: [Object],                                                                                                                                                                                                               
      variables: []                                                                                                                                                                                                                   
    },                                                                                                                                                                                                                                
    selfClosing: false,                                                                                                                                                                                                               
    attributes: [ [Object], [Circular *2] ]                                                                                                                                                                                           
  },                          
  directive: true,                                       
  key: <ref *3> {   
    type: 'VDirectiveKey',                               
    range: [ 3690, 3696 ],                                                                                         
    loc: { start: [Object], end: [Object] },                                                                       
    parent: [Circular *2],  
    name: {                                                                                                                                                                                                                           
      type: 'VIdentifier',                                                                                                                                                                                                            
      parent: [Circular *3],                                                                                                                                                                                                          
      range: [Array],                                                                                                                                                                                                                 
      loc: [Object],                         
      name: 'bind',                                                                                                                                                                                                                   
      rawName: ':'                                                                                                                                                                                                                    
    },                                                                                                             
    argument: {                                                                                                    
      type: 'VIdentifier',                                                                                         
      parent: [Circular *3],                             
      range: [Array],
      loc: [Object],
      name: 'class',
      rawName: 'class'
    },
    modifiers: []
  },
  value: {
    type: 'VExpressionContainer',
    range: [ 3697, 3769 ],
    loc: { start: [Object], end: [Object] },
    parent: [Circular *2],
    expression: null,
    references: []
  }
}
francoismassart commented 1 month ago

Thanks, I was able to reproduce the BUG then to confirm the fix is working as expected.