@spyglassmc/mcdoc 0.3.46 → 0.3.48

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.
@@ -0,0 +1,3 @@
1
+ import type { MetaRegistry } from '@spyglassmc/core';
2
+ export declare function registerMcdocChecker(meta: MetaRegistry): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,28 @@
1
+ import { localize } from '@spyglassmc/locales';
2
+ import { TypeDefSymbolData } from '../binder/index.js';
3
+ import { PathNode, ReferenceTypeNode, TypeArgBlockNode, TypeBaseNode } from '../node/index.js';
4
+ const reference = (node, ctx) => {
5
+ const { path } = ReferenceTypeNode.destruct(node);
6
+ const { children } = PathNode.destruct(path);
7
+ const symbol = children.findLast((c) => c.symbol && c.symbol.category === 'mcdoc' && c.symbol.subcategory !== 'module')?.symbol;
8
+ if (!TypeDefSymbolData.is(symbol?.data)) {
9
+ return;
10
+ }
11
+ const { appendixes } = TypeBaseNode.destruct(node);
12
+ let typeArgs = [];
13
+ if (TypeArgBlockNode.is(appendixes[0])) {
14
+ const { args } = TypeArgBlockNode.destruct(appendixes[0]);
15
+ typeArgs = args;
16
+ }
17
+ let typeParams = [];
18
+ if (symbol.data.typeDef.kind === 'template') {
19
+ typeParams = symbol.data.typeDef.typeParams;
20
+ }
21
+ if (typeParams.length !== typeArgs.length) {
22
+ ctx.err.report(localize('mcdoc.checker.reference.unexpected-number-of-type-arguments', symbol.identifier, typeParams.length, typeArgs.length), node);
23
+ }
24
+ };
25
+ export function registerMcdocChecker(meta) {
26
+ meta.registerChecker('mcdoc:type/reference', reference);
27
+ }
28
+ //# sourceMappingURL=index.js.map
package/lib/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type * as core from '@spyglassmc/core';
2
2
  export * as binder from './binder/index.js';
3
+ export * as checker from './checker/index.js';
3
4
  export * as colorizer from './colorizer/index.js';
4
5
  export * from './node/index.js';
5
6
  export * from './parser/index.js';
package/lib/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import * as binder from './binder/index.js';
2
+ import * as checker from './checker/index.js';
2
3
  import * as colorizer from './colorizer/index.js';
3
4
  import * as formatter from './formatter/index.js';
4
5
  import * as parser from './parser/index.js';
5
6
  import { registerBuiltinAttributes } from './runtime/attribute/builtin.js';
6
7
  import * as uri_professors from './uri_processors.js';
7
8
  export * as binder from './binder/index.js';
9
+ export * as checker from './checker/index.js';
8
10
  export * as colorizer from './colorizer/index.js';
9
11
  export * from './node/index.js';
10
12
  export * from './parser/index.js';
@@ -20,5 +22,6 @@ export const initialize = ({ meta }) => {
20
22
  binder.registerMcdocBinders(meta);
21
23
  colorizer.registerMcdocColorizer(meta);
22
24
  formatter.registerMcdocFormatter(meta);
25
+ checker.registerMcdocChecker(meta);
23
26
  };
24
27
  //# sourceMappingURL=index.js.map
@@ -289,6 +289,18 @@ export interface DocCommentsNode extends AstNode {
289
289
  export declare namespace DocCommentsNode {
290
290
  /**
291
291
  * @returns The text content of this doc comment block.
292
+ *
293
+ * If every line contains a leading space or is empty, stripe the leading spaces off.
294
+ * Trailing whitespace characters at the end are removed.
295
+ *
296
+ * e.g., given
297
+ * ```
298
+ * /// This is an example doc comment.
299
+ * ///
300
+ * /// Another line.
301
+ * ```
302
+ *
303
+ * "This is an example doc comment.\n\nAnother line." is returned.
292
304
  */
293
305
  function asText(node: DocCommentsNode | undefined): string | undefined;
294
306
  function is(node: AstNode | undefined): node is DocCommentsNode;
package/lib/node/index.js CHANGED
@@ -437,21 +437,29 @@ export var DocCommentsNode;
437
437
  (function (DocCommentsNode) {
438
438
  /**
439
439
  * @returns The text content of this doc comment block.
440
+ *
441
+ * If every line contains a leading space or is empty, stripe the leading spaces off.
442
+ * Trailing whitespace characters at the end are removed.
443
+ *
444
+ * e.g., given
445
+ * ```
446
+ * /// This is an example doc comment.
447
+ * ///
448
+ * /// Another line.
449
+ * ```
450
+ *
451
+ * "This is an example doc comment.\n\nAnother line." is returned.
440
452
  */
441
453
  function asText(node) {
442
454
  if (!node) {
443
455
  return undefined;
444
456
  }
445
457
  let comments = node.children.map((doc) => doc.comment);
446
- // If every comment contains a leading space or is empty, stripe the leading spaces off.
447
- // e.g. /// This is an example doc comment.
448
- // ///
449
- // /// Another line.
450
- // should be converted to "This is an example doc comment.\n\nAnother line."
451
- if (comments.every((s) => s.length === 0 || s.startsWith(' '))) {
452
- comments = comments.map((s) => s.slice(1));
458
+ // Note that each comment node includes the ending newline character.
459
+ if (comments.every((s) => !s.trim() || s.startsWith(' '))) {
460
+ comments = comments.map((s) => s.replace(/^ /, ''));
453
461
  }
454
- return comments.join('\n');
462
+ return comments.join('').trimEnd();
455
463
  }
456
464
  DocCommentsNode.asText = asText;
457
465
  function is(node) {
@@ -1,6 +1,7 @@
1
1
  import * as core from '@spyglassmc/core';
2
2
  import { localeQuote, localize } from '@spyglassmc/locales';
3
- import { registerAttribute, validator } from './index.js';
3
+ import { TypeDefSymbolData } from '../../binder/index.js';
4
+ import { registerAttribute, shouldKeepAccordingToAttributeFilters, validator } from './index.js';
4
5
  const idValidator = validator.alternatives(validator.map(validator.string, v => ({ registry: v })), validator.tree({
5
6
  registry: validator.string,
6
7
  tags: validator.optional(validator.options('allowed', 'implicit', 'required')),
@@ -60,7 +61,17 @@ export function registerBuiltinAttributes(meta) {
60
61
  registerAttribute(meta, 'dispatcher_key', validator.string, {
61
62
  stringMocker: (config, _, ctx) => {
62
63
  const symbol = ctx.symbols.query(ctx.doc, 'mcdoc/dispatcher', config).symbol;
63
- const keys = Object.keys(symbol?.members ?? {}).filter(m => !m.startsWith('%'));
64
+ const keys = Object.entries(symbol?.members ?? {})
65
+ .filter(([k, v]) => {
66
+ if (k.startsWith('%')) {
67
+ return false;
68
+ }
69
+ if (!TypeDefSymbolData.is(v.data)) {
70
+ return false;
71
+ }
72
+ return shouldKeepAccordingToAttributeFilters(v.data.typeDef.attributes, ctx);
73
+ })
74
+ .map(([k, _]) => k);
64
75
  return core.LiteralNode.mock(ctx.offset, { pool: keys });
65
76
  },
66
77
  });
@@ -21,4 +21,5 @@ interface AttributeInfo {
21
21
  }
22
22
  export declare function getAttribute(meta: core.MetaRegistry, name: string): AttributeInfo | undefined;
23
23
  export declare function handleAttributes(attributes: core.DeepReadonly<Attribute[]> | undefined, ctx: core.ContextBase, fn: <C>(handler: McdocAttribute<C>, config: C) => void): void;
24
+ export declare function shouldKeepAccordingToAttributeFilters(attributes: core.DeepReadonly<Attribute[]> | undefined, ctx: core.ContextBase): boolean;
24
25
  //# sourceMappingURL=index.d.ts.map
@@ -19,4 +19,16 @@ export function handleAttributes(attributes, ctx, fn) {
19
19
  fn(handler.attribute, config);
20
20
  }
21
21
  }
22
+ export function shouldKeepAccordingToAttributeFilters(attributes, ctx) {
23
+ let keep = true;
24
+ handleAttributes(attributes, ctx, (handler, config) => {
25
+ if (!keep || !handler.filterElement) {
26
+ return;
27
+ }
28
+ if (!handler.filterElement(config, ctx)) {
29
+ keep = false;
30
+ }
31
+ });
32
+ return keep;
33
+ }
22
34
  //# sourceMappingURL=index.js.map
@@ -2,7 +2,7 @@ import { Range, Source } from '@spyglassmc/core';
2
2
  import { localize } from '@spyglassmc/locales';
3
3
  import { TypeDefSymbolData } from '../../binder/index.js';
4
4
  import { McdocType, NumericRange } from '../../type/index.js';
5
- import { handleAttributes } from '../attribute/index.js';
5
+ import { handleAttributes, shouldKeepAccordingToAttributeFilters } from '../attribute/index.js';
6
6
  import { McdocCheckerContext } from './context.js';
7
7
  import { condenseAndPropagate } from './error.js';
8
8
  export * from './context.js';
@@ -604,6 +604,9 @@ function resolveIndices(parallelIndices, symbolMap, symbolQuery, context) {
604
604
  let dynamicData = false;
605
605
  let values = [];
606
606
  function pushValue(key, data) {
607
+ if (!shouldKeepAccordingToAttributeFilters(data.typeDef.attributes, context.ctx)) {
608
+ return;
609
+ }
607
610
  if (context.ctx.config.env.enableMcdocCaching && data.simplifiedTypeDef) {
608
611
  if (data.simplifiedTypeDef.kind === 'union') {
609
612
  values.push(...data.simplifiedTypeDef.members);
@@ -753,23 +756,11 @@ function resolveIndices(parallelIndices, symbolMap, symbolQuery, context) {
753
756
  }
754
757
  function simplifyUnion(typeDef, context) {
755
758
  let dynamicData = false;
756
- let validMembers = typeDef.members
757
- .filter(member => {
758
- let keep = true;
759
- handleAttributes(member.attributes, context.ctx, (handler, config) => {
760
- if (!keep || !handler.filterElement) {
761
- return;
762
- }
763
- if (!handler.filterElement(config, context.ctx)) {
764
- keep = false;
765
- }
766
- });
767
- return keep;
768
- });
759
+ let validMembers = typeDef.members.filter(member => shouldKeepAccordingToAttributeFilters(member.attributes, context.ctx));
769
760
  const filterCanonical = context.ctx.requireCanonical
770
761
  && validMembers.some(m => m.attributes?.some(a => a.name === 'canonical'));
771
762
  if (filterCanonical) {
772
- validMembers = typeDef.members.filter(member => member.attributes?.some(a => a.name === 'canonical'));
763
+ validMembers = validMembers.filter(member => member.attributes?.some(a => a.name === 'canonical'));
773
764
  }
774
765
  if (validMembers.length === 1) {
775
766
  return simplify(validMembers[0], context);
@@ -815,13 +806,7 @@ function simplifyStruct(typeDef, context) {
815
806
  }
816
807
  }
817
808
  for (const field of typeDef.fields) {
818
- let keep = true;
819
- handleAttributes(field.attributes, context.ctx, (handler, config) => {
820
- if (keep && handler.filterElement?.(config, context.ctx) === false) {
821
- keep = false;
822
- }
823
- });
824
- if (!keep) {
809
+ if (!shouldKeepAccordingToAttributeFilters(field.attributes, context.ctx)) {
825
810
  continue;
826
811
  }
827
812
  if (field.kind === 'pair') {
@@ -917,18 +902,7 @@ function simplifyTuple(typeDef, context) {
917
902
  };
918
903
  }
919
904
  function simplifyEnum(typeDef, context) {
920
- const filteredValues = typeDef.values.filter(value => {
921
- let keep = true;
922
- handleAttributes(value.attributes, context.ctx, (handler, config) => {
923
- if (!keep || !handler.filterElement) {
924
- return;
925
- }
926
- if (!handler.filterElement(config, context.ctx)) {
927
- keep = false;
928
- }
929
- });
930
- return keep;
931
- });
905
+ const filteredValues = typeDef.values.filter(value => shouldKeepAccordingToAttributeFilters(value.attributes, context.ctx));
932
906
  return { typeDef: { ...typeDef, enumKind: typeDef.enumKind ?? 'int', values: filteredValues } };
933
907
  }
934
908
  function simplifyConcrete(typeDef, context) {
@@ -1,5 +1,5 @@
1
1
  import { TypeDefSymbolData } from '../../binder/index.js';
2
- import { handleAttributes } from '../attribute/index.js';
2
+ import { handleAttributes, shouldKeepAccordingToAttributeFilters } from '../attribute/index.js';
3
3
  export function getFields(typeDef, ctx) {
4
4
  switch (typeDef.kind) {
5
5
  case 'union':
@@ -78,19 +78,7 @@ export function getValues(typeDef, ctx) {
78
78
  case 'boolean':
79
79
  return ['false', 'true'].map(v => ({ value: v, kind: 'boolean' }));
80
80
  case 'enum':
81
- // TODO: de-duplicate this logic from the runtime simplifier
82
- const filteredValues = typeDef.values.filter(value => {
83
- let keep = true;
84
- handleAttributes(value.attributes, ctx, (handler, config) => {
85
- if (!keep || !handler.filterElement) {
86
- return;
87
- }
88
- if (!handler.filterElement(config, ctx)) {
89
- keep = false;
90
- }
91
- });
92
- return keep;
93
- });
81
+ const filteredValues = typeDef.values.filter(value => shouldKeepAccordingToAttributeFilters(value.attributes, ctx));
94
82
  return filteredValues.map(v => ({
95
83
  value: `${v.value}`,
96
84
  detail: v.identifier,
@@ -27,7 +27,8 @@ export const uriBinder = (uris, ctx) => {
27
27
  // file:///root/mcdoc/foo/mod.mcdoc -> foo
28
28
  // file:///root/mcdoc/foo/bar.mcdoc -> foo/bar
29
29
  for (const [uri, rel] of urisAndRels) {
30
- ctx.symbols.query(uri, 'mcdoc', segToIdentifier(rel.split('/'))).ifKnown(() => { }).elseEnter({
30
+ ctx.symbols.query(uri, 'mcdoc', segToIdentifier(rel.split('/'))).ifDefined(() => { })
31
+ .elseEnter({
31
32
  data: { subcategory: 'module' },
32
33
  usage: { type: 'definition' },
33
34
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spyglassmc/mcdoc",
3
- "version": "0.3.46",
3
+ "version": "0.3.48",
4
4
  "type": "module",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -25,7 +25,7 @@
25
25
  "url": "https://github.com/SpyglassMC/Spyglass/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@spyglassmc/core": "0.4.42",
29
- "@spyglassmc/locales": "0.3.21"
28
+ "@spyglassmc/core": "0.4.44",
29
+ "@spyglassmc/locales": "0.3.23"
30
30
  }
31
31
  }