dot-language-support 4.3.0 → 4.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +93 -29
  2. package/package.json +6 -6
package/dist/index.mjs CHANGED
@@ -903,7 +903,7 @@ var Parser = class {
903
903
  const node = this.#createNode(syntaxKind.TextIdentifier);
904
904
  const text = this.scanner.tokenValue;
905
905
  this.#nextToken();
906
- if (text === void 0) throw "Satisfy type checker";
906
+ if (text === void 0) throw new Error("Token value is undefined");
907
907
  node.text = text;
908
908
  return this.#finishNode(node);
909
909
  }
@@ -917,7 +917,7 @@ var Parser = class {
917
917
  if (this.#token() === syntaxKind.PlusToken) this.#nextToken();
918
918
  const text = this.scanner.tokenValue;
919
919
  this.#nextToken();
920
- if (text === void 0) throw "Satisfy type checker";
920
+ if (text === void 0) throw new Error("Token value is undefined");
921
921
  node.text = text;
922
922
  return this.#finishNode(node);
923
923
  }
@@ -929,7 +929,7 @@ var Parser = class {
929
929
  const node = this.#createNode(syntaxKind.HtmlIdentifier);
930
930
  const text = this.scanner.tokenValue;
931
931
  this.#nextToken();
932
- if (text === void 0) throw "Satisfy type checker";
932
+ if (text === void 0) throw new Error("Token value is undefined");
933
933
  node.htmlContent = text;
934
934
  return this.#finishNode(node);
935
935
  }
@@ -937,7 +937,7 @@ var Parser = class {
937
937
  const node = this.#createNode(syntaxKind.NumericIdentifier);
938
938
  const text = this.scanner.tokenValue;
939
939
  this.#nextToken();
940
- if (text === void 0) throw "Satisfy type checker";
940
+ if (text === void 0) throw new Error("Token value is undefined");
941
941
  node.text = text;
942
942
  node.value = Number(text);
943
943
  return this.#finishNode(node);
@@ -962,7 +962,7 @@ var Parser = class {
962
962
  return this.#finishNode(subgraphStatement);
963
963
  }
964
964
  default: {
965
- if (!this.#isIdentifier) debugger;
965
+ if (!this.#isIdentifier()) debugger;
966
966
  if (this.#lookAhead(() => this.#isIdEqualsIdStatement())) return this.#parseIdEqualsIdStatement();
967
967
  const ns = this.#parseNodeStatement();
968
968
  if (ns.terminator !== void 0 || ns.attributes.length !== 0) return ns;
@@ -987,7 +987,7 @@ var Parser = class {
987
987
  node.terminator = this.#parseOptionalToken(syntaxKind.SemicolonToken);
988
988
  return this.#finishNode(node);
989
989
  }
990
- default: throw "This should never happen";
990
+ default: throw new Error("This should never happen");
991
991
  }
992
992
  }
993
993
  #parseAttributeContainer() {
@@ -1000,12 +1000,12 @@ var Parser = class {
1000
1000
  return this.#finishNode(node);
1001
1001
  }
1002
1002
  #isAssignmentStart() {
1003
- if (!this.#isIdentifier) debugger;
1003
+ if (!this.#isIdentifier()) debugger;
1004
1004
  this.#nextToken();
1005
1005
  return this.#token() === syntaxKind.EqualsToken;
1006
1006
  }
1007
1007
  #parseIdEqualsIdStatement() {
1008
- if (!this.#isIdentifier) debugger;
1008
+ if (!this.#isIdentifier()) debugger;
1009
1009
  const leftIdentifier = this.#parseIdentifier();
1010
1010
  const node = this.#createNode(syntaxKind.IdEqualsIdStatement, leftIdentifier.pos);
1011
1011
  node.leftId = leftIdentifier;
@@ -1016,12 +1016,12 @@ var Parser = class {
1016
1016
  return this.#finishNode(node);
1017
1017
  }
1018
1018
  #isIdEqualsIdStatement() {
1019
- if (!this.#isIdentifier) debugger;
1019
+ if (!this.#isIdentifier()) debugger;
1020
1020
  this.#nextToken();
1021
1021
  return this.#token() === syntaxKind.EqualsToken;
1022
1022
  }
1023
1023
  #parseNodeStatement() {
1024
- if (!this.#isIdentifier) debugger;
1024
+ if (!this.#isIdentifier()) debugger;
1025
1025
  const node = this.#createNode(syntaxKind.NodeStatement);
1026
1026
  node.id = this.#parseNodeId();
1027
1027
  if (this.#token() === syntaxKind.OpenBracketToken) node.attributes = this.#parseList(parsingContext.AttributeContainerList, () => this.#parseAttributeContainer());
@@ -1075,7 +1075,7 @@ var Parser = class {
1075
1075
  return this.#finishNode(result);
1076
1076
  }
1077
1077
  #parseAssignment() {
1078
- if (!this.#isIdentifier) debugger;
1078
+ if (!this.#isIdentifier()) debugger;
1079
1079
  const node = this.#createNode(syntaxKind.Assignment);
1080
1080
  node.leftId = this.#parseIdentifier();
1081
1081
  this.#parseExpectedToken(syntaxKind.EqualsToken);
@@ -1097,7 +1097,7 @@ var Parser = class {
1097
1097
  return this.#finishNode(node);
1098
1098
  }
1099
1099
  #parseNodeId() {
1100
- if (!this.#isIdentifier) debugger;
1100
+ if (!this.#isIdentifier()) debugger;
1101
1101
  const node = this.#createNode(syntaxKind.NodeId);
1102
1102
  node.id = this.#parseIdentifier();
1103
1103
  node.port = this.#token() === syntaxKind.ColonToken ? this.#parsePortDeclaration() : void 0;
@@ -1178,7 +1178,7 @@ var Parser = class {
1178
1178
  case parsingContext.EdgeRhsList: return this.#token() === syntaxKind.DirectedEdgeOp || this.#token() === syntaxKind.UndirectedEdgeOp;
1179
1179
  case parsingContext.QuotedTextIdentifierConcatenation: return this.#token() === syntaxKind.StringLiteral || this.#token() === syntaxKind.PlusToken;
1180
1180
  case parsingContext.StatementList: return this.#isIdentifier() || this.#token() === syntaxKind.SubgraphKeyword || this.#token() === syntaxKind.OpenBraceToken || this.#token() === syntaxKind.GraphKeyword || this.#token() === syntaxKind.EdgeKeyword || this.#token() === syntaxKind.NodeKeyword;
1181
- default: throw "This should never happen";
1181
+ default: throw new Error("This should never happen");
1182
1182
  }
1183
1183
  }
1184
1184
  #isListTerminator(context) {
@@ -1266,10 +1266,7 @@ var Parser = class {
1266
1266
  this.#parseErrorAtCurrentToken(msg, parseError.ExpectationFailed);
1267
1267
  }
1268
1268
  #parseExpectedOneOf(...kinds) {
1269
- if (kinds.length < 2) {
1270
- console.assert(false);
1271
- debugger;
1272
- }
1269
+ if (kinds.length < 2) console.assert(false);
1273
1270
  for (const kind of kinds) if (this.#token() === kind) {
1274
1271
  this.#nextToken();
1275
1272
  return true;
@@ -1278,10 +1275,7 @@ var Parser = class {
1278
1275
  return false;
1279
1276
  }
1280
1277
  #parseExpectedTokenOneOf(fallback, kinds) {
1281
- if (kinds.length < 2) {
1282
- console.assert(false);
1283
- debugger;
1284
- }
1278
+ if (kinds.length < 2) console.assert(false);
1285
1279
  for (const kind of kinds) if (this.#token() === kind) {
1286
1280
  const node = this.#createNode(this.#token());
1287
1281
  this.#nextToken();
@@ -1328,7 +1322,7 @@ var Parser = class {
1328
1322
  }
1329
1323
  }
1330
1324
  #isCompassPortKind(kind) {
1331
- return kind >= syntaxKind.CompassCenterToken && kind <= syntaxKind.CompassEnd;
1325
+ return kind >= syntaxKind.CompassBegin && kind <= syntaxKind.CompassEnd;
1332
1326
  }
1333
1327
  #speculationHelper(callback, isLookAhead) {
1334
1328
  const saveToken = this.#token();
@@ -1694,6 +1688,54 @@ const attributes = Array.from(new Set([
1694
1688
  ...graphAttributes,
1695
1689
  ...clusterAttributes
1696
1690
  ])).sort();
1691
+ const attributeDescriptions = Object.freeze({
1692
+ arrowhead: "Style of arrowhead at head end",
1693
+ arrowsize: "Scaling factor for arrowheads",
1694
+ arrowtail: "Style of arrowhead at tail end",
1695
+ bgcolor: "Background color",
1696
+ color: "Node shape/edge/cluster color",
1697
+ comment: "Any string",
1698
+ compound: "Allow edges between clusters",
1699
+ concentrate: "Enables edge concentrators",
1700
+ constraint: "Use edge to affect node ranking",
1701
+ decorate: "If set, line between label and edge",
1702
+ dir: "Direction of edge",
1703
+ distortion: "Node distortion",
1704
+ fillcolor: "Node/cluster fill color",
1705
+ fixedsize: "Label text has no effect on node size",
1706
+ fontcolor: "Font face color",
1707
+ fontname: "Font family",
1708
+ fontsize: "Point size of label",
1709
+ group: "Name of node group",
1710
+ headlabel: "Label placed near head of edge",
1711
+ headport: "Where on the node to attach head of edge",
1712
+ height: "Height in inches",
1713
+ label: "Any string",
1714
+ labelangle: "Angle in degrees",
1715
+ labeldistance: "Scaling factor for distance for head or tail label",
1716
+ labelfontcolor: "Type face color for head and tail labels",
1717
+ labelfontname: "Font family for head and tail labels",
1718
+ labelfontsize: "Point size for head and tail labels",
1719
+ labeljust: "Label justification",
1720
+ labelloc: "Label vertical justification",
1721
+ layer: "Overlay range",
1722
+ nodesep: "Separation between nodes, in inches",
1723
+ orientation: "Node rotation angle",
1724
+ peripheries: "Number of node boundaries",
1725
+ ranksep: "Separation between ranks, in inches",
1726
+ ratio: "Aspect ratio",
1727
+ regular: "Force polygon to be regular",
1728
+ rotate: "If 90, set orientation to landscape",
1729
+ shape: "Node shape",
1730
+ shapefile: "External custom shape file",
1731
+ sides: "Number of sides for shape=polygon",
1732
+ skew: "Skewing node for shape=polygon",
1733
+ style: "Graphics options",
1734
+ taillabel: "Label placed near tail of edge",
1735
+ tailport: "Where on the node to attach tail of edge",
1736
+ weight: "Integer cost of stretching an edge",
1737
+ width: "Width in inches"
1738
+ });
1697
1739
  /**
1698
1740
  * We only support the X11 color scheme
1699
1741
  */
@@ -2455,9 +2497,8 @@ function checkShapeLabelValues(root) {
2455
2497
  const invalidShapes = [];
2456
2498
  forEachAssignmentTransitive(root, (assignment) => {
2457
2499
  const { leftId, rightId } = assignment;
2458
- if (leftId.kind !== syntaxKind.TextIdentifier || rightId.kind !== syntaxKind.TextIdentifier) return;
2459
- if (leftId.text.trim().toLocaleLowerCase() !== "shape") return;
2460
- const rightText = rightId.text.trim();
2500
+ if (getIdentifierText(leftId).trim().toLowerCase() !== "shape") return;
2501
+ const rightText = getIdentifierText(rightId).trim();
2461
2502
  const shapeCandidate = rightText.toLowerCase();
2462
2503
  if (validShapesLowerCase.has(shapeCandidate)) return;
2463
2504
  invalidShapes.push({
@@ -3239,6 +3280,7 @@ function getAttributeCompletions(posistion) {
3239
3280
  return attributes.map((label) => ({
3240
3281
  kind,
3241
3282
  label,
3283
+ documentation: attributeDescriptions[label.toLowerCase()],
3242
3284
  textEdit: {
3243
3285
  range,
3244
3286
  newText: `${escapeIdentifierText(label)}=`
@@ -3310,8 +3352,12 @@ function getHoverContents(n) {
3310
3352
  return { contents: `(node) ${getIdentifierText(n)}` };
3311
3353
  case syntaxKind.Assignment: {
3312
3354
  const assignment = parent;
3355
+ const left = getIdentifierText(assignment.leftId);
3356
+ const right = getIdentifierText(assignment.rightId);
3357
+ const desc = attributeDescriptions[left.toLowerCase()];
3358
+ const base = `(assignment) \`${left}\` = \`${right}\``;
3313
3359
  return {
3314
- contents: `(assignment) \`${getIdentifierText(assignment.leftId)}\` = \`${getIdentifierText(assignment.rightId)}\``,
3360
+ contents: desc ? `${base}\n\n${desc}` : base,
3315
3361
  range: {
3316
3362
  pos: assignment.pos,
3317
3363
  end: assignment.end
@@ -3343,8 +3389,12 @@ function getHoverContents(n) {
3343
3389
  }
3344
3390
  case syntaxKind.IdEqualsIdStatement: {
3345
3391
  const idEqId = parent;
3392
+ const left = getIdentifierText(idEqId.leftId);
3393
+ const right = getIdentifierText(idEqId.rightId);
3394
+ const desc = attributeDescriptions[left.toLowerCase()];
3395
+ const base = `(graph property) \`${left}\` = \`${right}\``;
3346
3396
  return {
3347
- contents: `(graph property) \`${getIdentifierText(idEqId.leftId)}\` = \`${getIdentifierText(idEqId.rightId)}\``,
3397
+ contents: desc ? `${base}\n\n${desc}` : base,
3348
3398
  range: {
3349
3399
  pos: idEqId.pos,
3350
3400
  end: idEqId.end
@@ -3449,9 +3499,23 @@ function findDefinition(doc, sourceFile, position) {
3449
3499
  range
3450
3500
  };
3451
3501
  }
3452
- debugger;
3453
3502
  }
3454
- const findDeclaration = findDefinition;
3503
+ function findDeclaration(doc, sourceFile, position) {
3504
+ if (!sourceFile.symbols) throw "sourceFile is not bound";
3505
+ const g = sourceFile.graph;
3506
+ if (!g) return;
3507
+ const node = findNodeAtOffset(g, doc.offsetAt(position));
3508
+ if (!node) return;
3509
+ if (!isIdentifierNode(node)) return;
3510
+ const nodeSymbol = node.symbol;
3511
+ if (!nodeSymbol) throw "node.symbol is not bound";
3512
+ const firstUse = nodeSymbol.firstMention;
3513
+ if (!firstUse) return;
3514
+ return {
3515
+ uri: doc.uri,
3516
+ range: syntaxNodeToRange(doc, sourceFile, firstUse)
3517
+ };
3518
+ }
3455
3519
  //#endregion
3456
3520
  //#region src/service/rename.ts
3457
3521
  function renameSymbol(doc, sourceFile, position, newName) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dot-language-support",
3
- "version": "4.3.0",
3
+ "version": "4.3.2",
4
4
  "description": "Parser and language service for graphviz (dot) files",
5
5
  "keywords": [
6
6
  "dot",
@@ -35,11 +35,11 @@
35
35
  "vscode-languageserver-types": "^3.17.5"
36
36
  },
37
37
  "devDependencies": {
38
- "expect": "^30.3.0",
39
- "oxfmt": "^0.45.0",
40
- "oxlint": "^1.60.0",
41
- "oxlint-tsgolint": "^0.21.1",
42
- "tsdown": "^0.21.9",
38
+ "expect": "^30.4.1",
39
+ "oxfmt": "^0.52.0",
40
+ "oxlint": "^1.67.0",
41
+ "oxlint-tsgolint": "^0.23.0",
42
+ "tsdown": "^0.22.1",
43
43
  "typescript": "^6.0.3"
44
44
  },
45
45
  "engines": {