ifc-language-server/node_modules/@stylistic/eslint-plugin/dist/rules/jsx-function-call-newline.js
Ryan Schultz 8afacf268a Implemented a working Language Server Protocol (LSP) for IFC files with:
- Hover provider showing entity information and type
- Go-to-definition (F12) for entity references
- Basic IFC file validation (ISO-10303-21 header check)
- Entity parsing with regex-based detection
- Proper CommonJS module system (avoiding ES module issues)

This replaces the broken baseline from ifc-developer-tools which had:
- Non-functional ES module configuration
- Circular dependency issues
- Parser crashes
- Non-working PositionVisitor

Built on Microsoft's LSP example template for a clean, maintainable foundation.

Next: Add hierarchical entity dependency tree in hover tooltip."
2025-12-07 10:20:07 -06:00

92 lines
2.6 KiB
JavaScript

'use strict';
var utils = require('../utils.js');
require('eslint-visitor-keys');
require('espree');
require('estraverse');
const messages = {
missingLineBreak: "Missing line break around JSX"
};
function endWithComma(context, node) {
const sourceCode = context.sourceCode;
const nextToken = sourceCode.getTokenAfter(node);
return !!nextToken && nextToken.value === "," && nextToken.range[0] >= node.range[1];
}
var jsxFunctionCallNewline = utils.createRule({
name: "jsx-function-call-newline",
package: "jsx",
meta: {
type: "layout",
docs: {
description: "Enforce line breaks before and after JSX elements when they are used as arguments to a function."
},
fixable: "whitespace",
messages,
schema: [{
type: "string",
enum: ["always", "multiline"]
}]
},
create(context) {
const option = context.options[0] || "multiline";
function needsOpeningNewLine(node) {
const previousToken = context.sourceCode.getTokenBefore(node);
if (previousToken.loc.end.line === node.loc.start.line)
return true;
return false;
}
function needsClosingNewLine(node) {
const nextToken = context.sourceCode.getTokenAfter(node);
if (endWithComma(context, node))
return false;
if (node.loc.end.line === nextToken.loc.end.line)
return true;
return false;
}
function isMultilines(node) {
return node.loc.start.line !== node.loc.end.line;
}
function check(node) {
if (!node || !utils.isJSX(node))
return;
const sourceCode = context.sourceCode;
if (option === "always" || isMultilines(node)) {
const needsOpening = needsOpeningNewLine(node);
const needsClosing = needsClosingNewLine(node);
if (needsOpening || needsClosing) {
context.report({
node,
messageId: "missingLineBreak",
fix: (fixer) => {
const text = sourceCode.getText(node);
let fixed = text;
if (needsOpening)
fixed = `
${fixed}`;
if (needsClosing)
fixed = `${fixed}
`;
return fixer.replaceText(node, fixed);
}
});
}
}
}
function handleCallExpression(node) {
if (node.arguments.length === 0)
return;
node.arguments.forEach(check);
}
return {
CallExpression(node) {
handleCallExpression(node);
},
NewExpression(node) {
handleCallExpression(node);
}
};
}
});
module.exports = jsxFunctionCallNewline;