diff --git a/apps/api-extractor/src/generators/ApiModelGenerator.ts b/apps/api-extractor/src/generators/ApiModelGenerator.ts
index 5bb4d510608..cb0d52e17d3 100644
--- a/apps/api-extractor/src/generators/ApiModelGenerator.ts
+++ b/apps/api-extractor/src/generators/ApiModelGenerator.ts
@@ -202,6 +202,10 @@ export class ApiModelGenerator {
this._processApiProperty(astDeclaration, exportedName, parentApiItem);
break;
+ case ts.SyntaxKind.SetAccessor:
+ this._processApiProperty(astDeclaration, exportedName, parentApiItem);
+ break;
+
case ts.SyntaxKind.IndexSignature:
this._processApiIndexSignature(astDeclaration, exportedName, parentApiItem);
break;
@@ -817,13 +821,17 @@ export class ApiModelGenerator {
let apiProperty: ApiProperty | undefined = parentApiItem.tryGetMemberByKey(containerKey) as ApiProperty;
if (apiProperty === undefined) {
- const propertyDeclaration: ts.PropertyDeclaration =
- astDeclaration.declaration as ts.PropertyDeclaration;
-
const nodesToCapture: IExcerptBuilderNodeToCapture[] = [];
const propertyTypeTokenRange: IExcerptTokenRange = ExcerptBuilder.createEmptyTokenRange();
- nodesToCapture.push({ node: propertyDeclaration.type, tokenRange: propertyTypeTokenRange });
+
+ // If the property declaration's type is `undefined`, then we're processing a setter with no corresponding
+ // getter. Use the parameter type instead (note that TypeScript always reports an error if a setter
+ // does not have exactly one parameter).
+ const propertyTypeNode: ts.TypeNode | undefined =
+ (astDeclaration.declaration as ts.PropertyDeclaration | ts.GetAccessorDeclaration).type ||
+ (astDeclaration.declaration as ts.SetAccessorDeclaration).parameters[0].type;
+ nodesToCapture.push({ node: propertyTypeNode, tokenRange: propertyTypeTokenRange });
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
diff --git a/build-tests/api-documenter-test/config/api-extractor.json b/build-tests/api-documenter-test/config/api-extractor.json
index 5a21503f8df..17b82fa03cc 100644
--- a/build-tests/api-documenter-test/config/api-extractor.json
+++ b/build-tests/api-documenter-test/config/api-extractor.json
@@ -18,5 +18,14 @@
"enabled": false
},
- "testMode": true
+ "testMode": true,
+
+ "messages": {
+ "extractorMessageReporting": {
+ // Purposefully disabled for the `writeonlyProperty` test case.
+ "ae-missing-getter": {
+ "logLevel": "none"
+ }
+ }
+ }
}
diff --git a/build-tests/api-documenter-test/etc/api-documenter-test.api.json b/build-tests/api-documenter-test/etc/api-documenter-test.api.json
index 1474a9e2fe9..8ec69740667 100644
--- a/build-tests/api-documenter-test/etc/api-documenter-test.api.json
+++ b/build-tests/api-documenter-test/etc/api-documenter-test.api.json
@@ -905,6 +905,33 @@
"endIndex": 2
},
"isStatic": false
+ },
+ {
+ "kind": "Property",
+ "canonicalReference": "api-documenter-test!DocClass1#writeonlyProperty:member",
+ "docComment": "/**\n * API Extractor will surface an `ae-missing-getter` finding for this property.\n */\n",
+ "excerptTokens": [
+ {
+ "kind": "Content",
+ "text": "set writeonlyProperty(value: "
+ },
+ {
+ "kind": "Content",
+ "text": "string"
+ },
+ {
+ "kind": "Content",
+ "text": ");"
+ }
+ ],
+ "isOptional": false,
+ "releaseTag": "Public",
+ "name": "writeonlyProperty",
+ "propertyTypeTokenRange": {
+ "startIndex": 1,
+ "endIndex": 2
+ },
+ "isStatic": false
}
],
"extendsTokenRange": {
diff --git a/build-tests/api-documenter-test/etc/api-documenter-test.api.md b/build-tests/api-documenter-test/etc/api-documenter-test.api.md
index ab432523a49..828c30e2583 100644
--- a/build-tests/api-documenter-test/etc/api-documenter-test.api.md
+++ b/build-tests/api-documenter-test/etc/api-documenter-test.api.md
@@ -49,6 +49,7 @@ export class DocClass1 extends DocBaseClass implements IDocInterface1, IDocInter
// (undocumented)
get writeableProperty(): string;
set writeableProperty(value: string);
+ set writeonlyProperty(value: string);
}
// @public
diff --git a/build-tests/api-documenter-test/etc/markdown/api-documenter-test.docclass1.md b/build-tests/api-documenter-test/etc/markdown/api-documenter-test.docclass1.md
index 12107be9e13..0c0a9e42f51 100644
--- a/build-tests/api-documenter-test/etc/markdown/api-documenter-test.docclass1.md
+++ b/build-tests/api-documenter-test/etc/markdown/api-documenter-test.docclass1.md
@@ -38,6 +38,7 @@ The constructor for this class is marked as internal. Third-party code should no
| [readonlyProperty](./api-documenter-test.docclass1.readonlyproperty.md) | | string | |
| [regularProperty](./api-documenter-test.docclass1.regularproperty.md) | | [SystemEvent](./api-documenter-test.systemevent.md) | This is a regular property that happens to use the SystemEvent type. |
| [writeableProperty](./api-documenter-test.docclass1.writeableproperty.md) | | string | |
+| [writeonlyProperty](./api-documenter-test.docclass1.writeonlyproperty.md) | | string | API Extractor will surface an ae-missing-getter finding for this property. |
## Methods
diff --git a/build-tests/api-documenter-test/etc/markdown/api-documenter-test.docclass1.writeonlyproperty.md b/build-tests/api-documenter-test/etc/markdown/api-documenter-test.docclass1.writeonlyproperty.md
new file mode 100644
index 00000000000..c67cc8b01dd
--- /dev/null
+++ b/build-tests/api-documenter-test/etc/markdown/api-documenter-test.docclass1.writeonlyproperty.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [api-documenter-test](./api-documenter-test.md) > [DocClass1](./api-documenter-test.docclass1.md) > [writeonlyProperty](./api-documenter-test.docclass1.writeonlyproperty.md)
+
+## DocClass1.writeonlyProperty property
+
+API Extractor will surface an `ae-missing-getter` finding for this property.
+
+Signature:
+
+```typescript
+set writeonlyProperty(value: string);
+```
diff --git a/build-tests/api-documenter-test/etc/yaml/api-documenter-test/docclass1.yml b/build-tests/api-documenter-test/etc/yaml/api-documenter-test/docclass1.yml
index cbe85393815..b02c6cb4ff3 100644
--- a/build-tests/api-documenter-test/etc/yaml/api-documenter-test/docclass1.yml
+++ b/build-tests/api-documenter-test/etc/yaml/api-documenter-test/docclass1.yml
@@ -61,6 +61,19 @@ properties:
set writeableProperty(value: string);
return:
type: string
+ - name: writeonlyProperty
+ uid: 'api-documenter-test!DocClass1#writeonlyProperty:member'
+ package: api-documenter-test!
+ fullName: writeonlyProperty
+ summary: API Extractor will surface an `ae-missing-getter` finding for this property.
+ remarks: ''
+ example: []
+ isPreview: false
+ isDeprecated: false
+ syntax:
+ content: 'set writeonlyProperty(value: string);'
+ return:
+ type: string
methods:
- name: deprecatedExample()
uid: 'api-documenter-test!DocClass1#deprecatedExample:member(1)'
diff --git a/build-tests/api-documenter-test/src/DocClass1.ts b/build-tests/api-documenter-test/src/DocClass1.ts
index 2de7efe031f..313a0f45a95 100644
--- a/build-tests/api-documenter-test/src/DocClass1.ts
+++ b/build-tests/api-documenter-test/src/DocClass1.ts
@@ -206,6 +206,11 @@ export class DocClass1 extends DocBaseClass implements IDocInterface1, IDocInter
}
public set writeableProperty(value: string) {}
+ /**
+ * API Extractor will surface an `ae-missing-getter` finding for this property.
+ */
+ public set writeonlyProperty(value: string) {}
+
/**
* This event is fired whenever the object is modified.
* @eventProperty
diff --git a/build-tests/install-test-workspace/workspace/common/pnpm-lock.yaml b/build-tests/install-test-workspace/workspace/common/pnpm-lock.yaml
index 3fafc4e2348..da643175830 100644
--- a/build-tests/install-test-workspace/workspace/common/pnpm-lock.yaml
+++ b/build-tests/install-test-workspace/workspace/common/pnpm-lock.yaml
@@ -4,28 +4,28 @@ importers:
typescript-newest-test:
specifiers:
- '@rushstack/eslint-config': file:rushstack-eslint-config-2.5.4.tgz
- '@rushstack/heft': file:rushstack-heft-0.44.13.tgz
+ '@rushstack/eslint-config': file:rushstack-eslint-config-2.6.0.tgz
+ '@rushstack/heft': file:rushstack-heft-0.45.0.tgz
eslint: ~8.7.0
tslint: ~5.20.1
typescript: ~4.6.3
devDependencies:
- '@rushstack/eslint-config': file:../temp/tarballs/rushstack-eslint-config-2.5.4.tgz_eslint@8.7.0+typescript@4.6.3
- '@rushstack/heft': file:../temp/tarballs/rushstack-heft-0.44.13.tgz
+ '@rushstack/eslint-config': file:../temp/tarballs/rushstack-eslint-config-2.6.0.tgz_eslint@8.7.0+typescript@4.6.3
+ '@rushstack/heft': file:../temp/tarballs/rushstack-heft-0.45.0.tgz
eslint: 8.7.0
tslint: 5.20.1_typescript@4.6.3
typescript: 4.6.3
typescript-v3-test:
specifiers:
- '@rushstack/eslint-config': file:rushstack-eslint-config-2.5.4.tgz
- '@rushstack/heft': file:rushstack-heft-0.44.13.tgz
+ '@rushstack/eslint-config': file:rushstack-eslint-config-2.6.0.tgz
+ '@rushstack/heft': file:rushstack-heft-0.45.0.tgz
eslint: ~8.7.0
tslint: ~5.20.1
typescript: ~4.6.3
devDependencies:
- '@rushstack/eslint-config': file:../temp/tarballs/rushstack-eslint-config-2.5.4.tgz_eslint@8.7.0+typescript@4.6.3
- '@rushstack/heft': file:../temp/tarballs/rushstack-heft-0.44.13.tgz
+ '@rushstack/eslint-config': file:../temp/tarballs/rushstack-eslint-config-2.6.0.tgz_eslint@8.7.0+typescript@4.6.3
+ '@rushstack/heft': file:../temp/tarballs/rushstack-heft-0.45.0.tgz
eslint: 8.7.0
tslint: 5.20.1_typescript@4.6.3
typescript: 4.6.3
@@ -1673,19 +1673,19 @@ packages:
commander: 2.20.3
dev: true
- file:../temp/tarballs/rushstack-eslint-config-2.5.4.tgz_eslint@8.7.0+typescript@4.6.3:
- resolution: {tarball: file:../temp/tarballs/rushstack-eslint-config-2.5.4.tgz}
- id: file:../temp/tarballs/rushstack-eslint-config-2.5.4.tgz
+ file:../temp/tarballs/rushstack-eslint-config-2.6.0.tgz_eslint@8.7.0+typescript@4.6.3:
+ resolution: {tarball: file:../temp/tarballs/rushstack-eslint-config-2.6.0.tgz}
+ id: file:../temp/tarballs/rushstack-eslint-config-2.6.0.tgz
name: '@rushstack/eslint-config'
- version: 2.5.4
+ version: 2.6.0
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
typescript: '>=3.0.0'
dependencies:
'@rushstack/eslint-patch': file:../temp/tarballs/rushstack-eslint-patch-1.1.3.tgz
- '@rushstack/eslint-plugin': file:../temp/tarballs/rushstack-eslint-plugin-0.8.6.tgz_eslint@8.7.0+typescript@4.6.3
- '@rushstack/eslint-plugin-packlets': file:../temp/tarballs/rushstack-eslint-plugin-packlets-0.3.6.tgz_eslint@8.7.0+typescript@4.6.3
- '@rushstack/eslint-plugin-security': file:../temp/tarballs/rushstack-eslint-plugin-security-0.2.6.tgz_eslint@8.7.0+typescript@4.6.3
+ '@rushstack/eslint-plugin': file:../temp/tarballs/rushstack-eslint-plugin-0.9.0.tgz_eslint@8.7.0+typescript@4.6.3
+ '@rushstack/eslint-plugin-packlets': file:../temp/tarballs/rushstack-eslint-plugin-packlets-0.4.0.tgz_eslint@8.7.0+typescript@4.6.3
+ '@rushstack/eslint-plugin-security': file:../temp/tarballs/rushstack-eslint-plugin-security-0.3.0.tgz_eslint@8.7.0+typescript@4.6.3
'@typescript-eslint/eslint-plugin': 5.20.0_e20e806d7f50be84027c83f3a408385a
'@typescript-eslint/experimental-utils': 5.20.0_eslint@8.7.0+typescript@4.6.3
'@typescript-eslint/parser': 5.20.0_eslint@8.7.0+typescript@4.6.3
@@ -1705,11 +1705,11 @@ packages:
version: 1.1.3
dev: true
- file:../temp/tarballs/rushstack-eslint-plugin-0.8.6.tgz_eslint@8.7.0+typescript@4.6.3:
- resolution: {tarball: file:../temp/tarballs/rushstack-eslint-plugin-0.8.6.tgz}
- id: file:../temp/tarballs/rushstack-eslint-plugin-0.8.6.tgz
+ file:../temp/tarballs/rushstack-eslint-plugin-0.9.0.tgz_eslint@8.7.0+typescript@4.6.3:
+ resolution: {tarball: file:../temp/tarballs/rushstack-eslint-plugin-0.9.0.tgz}
+ id: file:../temp/tarballs/rushstack-eslint-plugin-0.9.0.tgz
name: '@rushstack/eslint-plugin'
- version: 0.8.6
+ version: 0.9.0
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
@@ -1721,11 +1721,11 @@ packages:
- typescript
dev: true
- file:../temp/tarballs/rushstack-eslint-plugin-packlets-0.3.6.tgz_eslint@8.7.0+typescript@4.6.3:
- resolution: {tarball: file:../temp/tarballs/rushstack-eslint-plugin-packlets-0.3.6.tgz}
- id: file:../temp/tarballs/rushstack-eslint-plugin-packlets-0.3.6.tgz
+ file:../temp/tarballs/rushstack-eslint-plugin-packlets-0.4.0.tgz_eslint@8.7.0+typescript@4.6.3:
+ resolution: {tarball: file:../temp/tarballs/rushstack-eslint-plugin-packlets-0.4.0.tgz}
+ id: file:../temp/tarballs/rushstack-eslint-plugin-packlets-0.4.0.tgz
name: '@rushstack/eslint-plugin-packlets'
- version: 0.3.6
+ version: 0.4.0
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
@@ -1737,11 +1737,11 @@ packages:
- typescript
dev: true
- file:../temp/tarballs/rushstack-eslint-plugin-security-0.2.6.tgz_eslint@8.7.0+typescript@4.6.3:
- resolution: {tarball: file:../temp/tarballs/rushstack-eslint-plugin-security-0.2.6.tgz}
- id: file:../temp/tarballs/rushstack-eslint-plugin-security-0.2.6.tgz
+ file:../temp/tarballs/rushstack-eslint-plugin-security-0.3.0.tgz_eslint@8.7.0+typescript@4.6.3:
+ resolution: {tarball: file:../temp/tarballs/rushstack-eslint-plugin-security-0.3.0.tgz}
+ id: file:../temp/tarballs/rushstack-eslint-plugin-security-0.3.0.tgz
name: '@rushstack/eslint-plugin-security'
- version: 0.2.6
+ version: 0.3.0
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
@@ -1753,17 +1753,17 @@ packages:
- typescript
dev: true
- file:../temp/tarballs/rushstack-heft-0.44.13.tgz:
- resolution: {tarball: file:../temp/tarballs/rushstack-heft-0.44.13.tgz}
+ file:../temp/tarballs/rushstack-heft-0.45.0.tgz:
+ resolution: {tarball: file:../temp/tarballs/rushstack-heft-0.45.0.tgz}
name: '@rushstack/heft'
- version: 0.44.13
+ version: 0.45.0
engines: {node: '>=10.13.0'}
hasBin: true
dependencies:
- '@rushstack/heft-config-file': file:../temp/tarballs/rushstack-heft-config-file-0.8.2.tgz
- '@rushstack/node-core-library': file:../temp/tarballs/rushstack-node-core-library-3.45.3.tgz
- '@rushstack/rig-package': file:../temp/tarballs/rushstack-rig-package-0.3.10.tgz
- '@rushstack/ts-command-line': file:../temp/tarballs/rushstack-ts-command-line-4.10.9.tgz
+ '@rushstack/heft-config-file': file:../temp/tarballs/rushstack-heft-config-file-0.8.3.tgz
+ '@rushstack/node-core-library': file:../temp/tarballs/rushstack-node-core-library-3.45.4.tgz
+ '@rushstack/rig-package': file:../temp/tarballs/rushstack-rig-package-0.3.11.tgz
+ '@rushstack/ts-command-line': file:../temp/tarballs/rushstack-ts-command-line-4.10.10.tgz
'@types/tapable': 1.0.6
argparse: 1.0.10
chokidar: 3.4.3
@@ -1776,21 +1776,21 @@ packages:
true-case-path: 2.2.1
dev: true
- file:../temp/tarballs/rushstack-heft-config-file-0.8.2.tgz:
- resolution: {tarball: file:../temp/tarballs/rushstack-heft-config-file-0.8.2.tgz}
+ file:../temp/tarballs/rushstack-heft-config-file-0.8.3.tgz:
+ resolution: {tarball: file:../temp/tarballs/rushstack-heft-config-file-0.8.3.tgz}
name: '@rushstack/heft-config-file'
- version: 0.8.2
+ version: 0.8.3
engines: {node: '>=10.13.0'}
dependencies:
- '@rushstack/node-core-library': file:../temp/tarballs/rushstack-node-core-library-3.45.3.tgz
- '@rushstack/rig-package': file:../temp/tarballs/rushstack-rig-package-0.3.10.tgz
+ '@rushstack/node-core-library': file:../temp/tarballs/rushstack-node-core-library-3.45.4.tgz
+ '@rushstack/rig-package': file:../temp/tarballs/rushstack-rig-package-0.3.11.tgz
jsonpath-plus: 4.0.0
dev: true
- file:../temp/tarballs/rushstack-node-core-library-3.45.3.tgz:
- resolution: {tarball: file:../temp/tarballs/rushstack-node-core-library-3.45.3.tgz}
+ file:../temp/tarballs/rushstack-node-core-library-3.45.4.tgz:
+ resolution: {tarball: file:../temp/tarballs/rushstack-node-core-library-3.45.4.tgz}
name: '@rushstack/node-core-library'
- version: 3.45.3
+ version: 3.45.4
dependencies:
'@types/node': 12.20.24
colors: 1.2.5
@@ -1803,10 +1803,10 @@ packages:
z-schema: 5.0.2
dev: true
- file:../temp/tarballs/rushstack-rig-package-0.3.10.tgz:
- resolution: {tarball: file:../temp/tarballs/rushstack-rig-package-0.3.10.tgz}
+ file:../temp/tarballs/rushstack-rig-package-0.3.11.tgz:
+ resolution: {tarball: file:../temp/tarballs/rushstack-rig-package-0.3.11.tgz}
name: '@rushstack/rig-package'
- version: 0.3.10
+ version: 0.3.11
dependencies:
resolve: 1.17.0
strip-json-comments: 3.1.1
@@ -1818,10 +1818,10 @@ packages:
version: 0.2.3
dev: true
- file:../temp/tarballs/rushstack-ts-command-line-4.10.9.tgz:
- resolution: {tarball: file:../temp/tarballs/rushstack-ts-command-line-4.10.9.tgz}
+ file:../temp/tarballs/rushstack-ts-command-line-4.10.10.tgz:
+ resolution: {tarball: file:../temp/tarballs/rushstack-ts-command-line-4.10.10.tgz}
name: '@rushstack/ts-command-line'
- version: 4.10.9
+ version: 4.10.10
dependencies:
'@types/argparse': 1.0.38
argparse: 1.0.10
diff --git a/common/changes/@microsoft/api-extractor/handle-setters_2022-05-05-17-41.json b/common/changes/@microsoft/api-extractor/handle-setters_2022-05-05-17-41.json
new file mode 100644
index 00000000000..4c4bd34687d
--- /dev/null
+++ b/common/changes/@microsoft/api-extractor/handle-setters_2022-05-05-17-41.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@microsoft/api-extractor",
+ "comment": "Generate API doc model nodes for setters without getters",
+ "type": "minor"
+ }
+ ],
+ "packageName": "@microsoft/api-extractor"
+}
\ No newline at end of file