Skip to content

Commit f7bcd53

Browse files
committed
Added examples in docs, added IApiDefinitionReferenceParts to avoid confusion, changed IScopePackageName to IScopedPackageName
1 parent 2b99aac commit f7bcd53

6 files changed

Lines changed: 85 additions & 100 deletions

File tree

Lines changed: 70 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,45 @@
1+
/**
2+
* An API definition reference that is used to locate the documentation of exported
3+
* API items that may or may not belong to an external package.
4+
*
5+
* The format of the API definition reference is:
6+
* scopeName/packageName:exportName.memberName
7+
*
8+
* The following are valid API definition references:
9+
* \@microsoft/sp-core-library:DisplayMode
10+
* \@microsoft/sp-core-library:Guid
11+
* \@microsoft/sp-core-library:Guid.equals
12+
* es6-collections:Map
13+
*/
14+
export interface IApiDefinintionReferenceParts {
15+
/**
16+
* This is an optional property to denote that a package name is scoped under this name.
17+
* For example, a common case is when having the '@microsoft' scope name in the
18+
* API definition reference: '\@microsoft/sp-core-library'.
19+
*/
20+
scopeName: string;
21+
/**
22+
* The name of the package that the exportName belongs to.
23+
*/
24+
packageName: string;
25+
/**
26+
* The name of the export API item.
27+
*/
28+
exportName: string;
29+
/**
30+
* The name of the member API item.
31+
*/
32+
memberName: string;
33+
}
34+
135
/**
236
* A scope and package name are semantic information within an API reference expression.
37+
* If there is no scope or package, then the corresponding values will be an empty string.
38+
*
39+
* Example: '@microsoft/Utilities' -> \{ scope: '@microsoft', package: 'Utilities' \}
40+
* Example: 'Utilities' -> \{ scope: '', package: 'Utilities' \}
341
*/
4-
export interface IScopePackageName {
42+
export interface IScopedPackageName {
543
/**
644
* The scope name of an API reference expression.
745
*/
@@ -14,17 +52,7 @@ export interface IScopePackageName {
1452
}
1553

1654
/**
17-
* An API definition reference that is used to locate the documentation of exported
18-
* API items that may or may not belong to an external package.
19-
*
20-
* The format of the API definition reference is:
21-
* scopeName/packageName:exportName.memberName
22-
*
23-
* The following are valid API definition references:
24-
* \@microsoft/sp-core-library:DisplayMode
25-
* \@microsoft/sp-core-library:Guid
26-
* \@microsoft/sp-core-library:Guid.equals
27-
* es6-collections:Map
55+
* {@inheritdoc IApiDefinintionReferenceParts}
2856
*/
2957
export default class ApiDefinitionReference {
3058
/**
@@ -44,33 +72,28 @@ export default class ApiDefinitionReference {
4472
private static _exportRegEx: RegExp = /^\w+/;
4573

4674
/**
47-
* This is an optional property to denote that a package name is scoped under this name.
48-
* For example, a common case is when having the '@microsoft' scope name in the
49-
* API definition reference: '\@microsoft/sp-core-library'.
75+
* {@inheritdoc IApiDefinintionReferenceParts.scopeName}
5076
*/
5177
public scopeName: string;
5278
/**
53-
* The name of the package that the exportName belongs to.
79+
* {@inheritdoc IApiDefinintionReferenceParts.packageName}
5480
*/
5581
public packageName: string;
5682
/**
57-
* The name of the export API item.
83+
* {@inheritdoc IApiDefinintionReferenceParts.exportName}
5884
*/
5985
public exportName: string;
6086
/**
61-
* The name of the member API item.
87+
* {@inheritdoc IApiDefinintionReferenceParts.memberName}
6288
*/
6389
public memberName: string;
6490

6591
/**
6692
* Creates an ApiDefinitionReference instance given strings that symbolize the public
6793
* properties of ApiDefinitionReference.
6894
*/
69-
public static createFromParts(scopeName: string,
70-
packageName: string,
71-
exportName: string,
72-
memberName: string): ApiDefinitionReference {
73-
return new ApiDefinitionReference(scopeName, packageName, exportName, memberName);
95+
public static createFromParts(parts: IApiDefinintionReferenceParts): ApiDefinitionReference {
96+
return new ApiDefinitionReference(parts);
7497
}
7598

7699
/**
@@ -86,26 +109,28 @@ export default class ApiDefinitionReference {
86109
return;
87110
}
88111

89-
let scopeName: string = '';
90-
let packageName: string = '';
91-
let exportName: string = '';
92-
let memberName: string = '';
112+
const apiDefRefParts: IApiDefinintionReferenceParts = {
113+
scopeName: '',
114+
packageName: '',
115+
exportName: '',
116+
memberName: ''
117+
};
93118

94119
// E.g. @microsoft/sp-core-library:Guid.equals
95120
let parts: string[] = apiReferenceExpr.match(ApiDefinitionReference._packageRegEx);
96121
if (parts) {
97122
// parts[1] is of the form ‘@microsoft/sp-core-library’ or ‘sp-core-library’
98-
const scopePackageName: IScopePackageName = ApiDefinitionReference.parseScopedPackageName(parts[1]);
99-
scopeName = scopePackageName.scope;
100-
packageName = scopePackageName.package;
123+
const scopePackageName: IScopedPackageName = ApiDefinitionReference.parseScopedPackageName(parts[1]);
124+
apiDefRefParts.scopeName = scopePackageName.scope;
125+
apiDefRefParts.packageName = scopePackageName.package;
101126
apiReferenceExpr = parts[2]; // e.g. Guid.equals
102127
}
103128

104129
// E.g. Guid.equals
105130
parts = apiReferenceExpr.match(ApiDefinitionReference._memberRegEx);
106131
if (parts) {
107-
exportName = parts[1]; // e.g. Guid, can never be undefined
108-
memberName = parts[2] ? parts[2] : ''; // e.g. equals
132+
apiDefRefParts.exportName = parts[1]; // e.g. Guid, can never be undefined
133+
apiDefRefParts.memberName = parts[2] ? parts[2] : ''; // e.g. equals
109134
} else {
110135
// the export name is required
111136
throw reportError(`Api reference expression contains invalid characters: ${apiReferenceExpr}`);
@@ -115,15 +140,15 @@ export default class ApiDefinitionReference {
115140
throw reportError(`Api reference expression contains invalid characters: ${apiReferenceExpr}`);
116141
}
117142

118-
return ApiDefinitionReference.createFromParts(scopeName, packageName, exportName, memberName);
143+
return ApiDefinitionReference.createFromParts(apiDefRefParts);
119144
}
120145

121146
/**
122147
* For a scoped NPM package name this separates the scope and package parts. For example:
123148
* parseScopedPackageName('@my-scope/myproject') = { scope: '@my-scope', package: 'myproject' }
124149
* parseScopedPackageName('myproject') = { scope: '', package: 'myproject' }
125150
*/
126-
public static parseScopedPackageName(scopedName: string): IScopePackageName {
151+
public static parseScopedPackageName(scopedName: string): IScopedPackageName {
127152
if (scopedName.substr(0, 1) !== '@') {
128153
return { scope: '', package: scopedName };
129154
}
@@ -136,25 +161,11 @@ export default class ApiDefinitionReference {
136161
}
137162
}
138163

139-
/**
140-
* Seperates the name property of an ApiPackage into a scope name and the actual
141-
* name of the package.
142-
*/
143-
public static parseApiPackageName(apiPackageName: string): IScopePackageName {
144-
const slashIndex: number = apiPackageName.indexOf('/');
145-
if (slashIndex >= 0) {
146-
return {
147-
scope: apiPackageName.substr(0, slashIndex),
148-
package: apiPackageName.substr(slashIndex + 1)
149-
};
150-
} else {
151-
return { scope: '', package: apiPackageName.substr(slashIndex + 1) };
152-
}
153-
}
154-
155164
/**
156165
* Stringifies the ApiDefinitionReferenceOptions up and including the
157166
* scope and package name.
167+
*
168+
* Example output: '@microsoft/Utilities'
158169
*/
159170
public toScopePackageString(): string {
160171
let result: string = '';
@@ -169,6 +180,8 @@ export default class ApiDefinitionReference {
169180
/**
170181
* Stringifies the ApiDefinitionReferenceOptions up and including the
171182
* scope, package and export name.
183+
*
184+
* Example output: '@microsoft/Utilities.Parse'
172185
*/
173186
public toExportString(): string {
174187
let result: string = this.toScopePackageString();
@@ -181,15 +194,17 @@ export default class ApiDefinitionReference {
181194
/**
182195
* Stringifies the ApiDefinitionReferenceOptions up and including the
183196
* scope, package, export and member name.
197+
*
198+
* Example output: '@microsoft/Utilities.Parse.parseJsonToString'
184199
*/
185200
public toMemberString(): string {
186201
return this.toExportString() + `.${this.memberName}`;
187202
}
188203

189-
private constructor(scopeName: string, packageName: string, exportName: string, memberName: string) {
190-
this.scopeName = scopeName;
191-
this.packageName = packageName;
192-
this.exportName = exportName;
193-
this.memberName = memberName;
204+
private constructor(parts: IApiDefinintionReferenceParts) {
205+
this.scopeName = parts.scopeName;
206+
this.packageName = parts.packageName;
207+
this.exportName = parts.exportName;
208+
this.memberName = parts.memberName;
194209
}
195210
}

api-extractor/src/DebugRun.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as os from 'os';
66
import Extractor from './Extractor';
77
import ApiFileGenerator from './generators/ApiFileGenerator';
88
import ApiJsonGenerator from './generators/ApiJsonGenerator';
9-
import ApiDefinitionReference from './ApiDefinitionReference';
9+
import ApiDefinitionReference, { IApiDefinintionReferenceParts } from './ApiDefinitionReference';
1010

1111
const compilerOptions: ts.CompilerOptions = {
1212
target: ts.ScriptTarget.ES5,
@@ -32,13 +32,14 @@ extractor.loadExternalPackages('./testInputs/external-api-json');
3232
extractor.analyze({entryPointFile: './testInputs/example2/index.ts',
3333
otherFiles: []});
3434

35-
const externalPackageApiRef: ApiDefinitionReference = ApiDefinitionReference.createFromParts(
36-
'',
37-
'es6-collections',
38-
'',
39-
''
40-
);
41-
console.log(extractor.docItemLoader.getPackage(externalPackageApiRef, console.log));
35+
const externalPackageApiRef: IApiDefinintionReferenceParts = {
36+
scopeName: '',
37+
packageName: 'es6-collections',
38+
exportName: '',
39+
memberName: ''
40+
};
41+
const apiDefinitionRef: ApiDefinitionReference = ApiDefinitionReference.createFromParts(externalPackageApiRef);
42+
console.log(extractor.docItemLoader.getPackage(apiDefinitionRef, console.log));
4243

4344
const apiFileGenerator: ApiFileGenerator = new ApiFileGenerator();
4445
apiFileGenerator.writeApiFile('./lib/DebugRun.api.ts', extractor);

api-extractor/src/DocItemLoader.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as fsx from 'fs-extra';
22
import * as os from 'os';
33
import * as path from 'path';
44
import { IDocItem, IDocPackage, IDocMember } from './IDocItem';
5-
import ApiDefinitionReference, { IScopePackageName } from './ApiDefinitionReference';
5+
import ApiDefinitionReference, { IScopedPackageName, IApiDefinintionReferenceParts } from './ApiDefinitionReference';
66
import ApiItem from './definitions/ApiItem';
77
import ApiItemContainer from './definitions/ApiItemContainer';
88
import ApiPackage from './definitions/ApiPackage';
@@ -56,21 +56,10 @@ export default class DocItemLoader {
5656
apiPackage: ApiPackage,
5757
reportError: (message: string) => void): ResolvedApiItem {
5858

59-
const scopePackageName: IScopePackageName = ApiDefinitionReference.parseApiPackageName(
60-
path.dirname(apiPackage.name)
61-
);
62-
const currentScopeName: string = scopePackageName.scope;
63-
const currentPackageName: string = scopePackageName.package;
64-
65-
const packageNameMatch: boolean = apiDefinitionRef.packageName ?
66-
apiDefinitionRef.packageName === currentPackageName : true;
67-
const scopeNameMatch: boolean = apiDefinitionRef.scopeName ?
68-
apiDefinitionRef.scopeName === currentScopeName : true;
69-
7059
// If there is a packageName then there must be a scopeName, and they
7160
// both must match the current scope and package we are in.
72-
// We can take advantage of '&&' being evaluated left to right.
73-
if (packageNameMatch && scopeNameMatch) {
61+
// We can take advantage of '&&' being evaluated left to right.
62+
if (!apiDefinitionRef.packageName && !apiDefinitionRef.scopeName) {
7463
// Resolution for local references
7564
return this.resolveLocalReferences(apiDefinitionRef, apiPackage, reportError);
7665
} else {

api-extractor/testInputs/example3/example3-output.json

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
"remarks": [],
8888
"isBeta": false
8989
},
90-
"inheritLocalOptionThreeFunction": {
90+
"inheritLocalOptionTwoFunction": {
9191
"kind": "function",
9292
"returnValue": {
9393
"type": "void",
@@ -104,19 +104,6 @@
104104
"remarks": [],
105105
"isBeta": false
106106
},
107-
"inheritLocalOptionTwo": {
108-
"kind": "enum",
109-
"values": {},
110-
"deprecatedMessage": [],
111-
"summary": [
112-
{
113-
"kind": "textDocElement",
114-
"value": "This is the summary for MyClass."
115-
}
116-
],
117-
"remarks": [],
118-
"isBeta": false
119-
},
120107
"IStructuredTypeInherit": {
121108
"kind": "interface",
122109
"extends": "",

api-extractor/testInputs/example3/folder/MyClass.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,11 @@
44
export enum inheritLocalOptionOne {
55
}
66

7-
/**
8-
* {@inheritdoc example3:MyClass }
9-
*/
10-
export enum inheritLocalOptionTwo {
11-
}
12-
137
/**
148
* {@inheritdoc MyClass.methodWithTwoParams }
159
*/
1610
// (Error #1) methodWithTwoParams not a member of MyClass
17-
export function inheritLocalOptionThreeFunction(): void {
11+
export function inheritLocalOptionTwoFunction(): void {
1812
}
1913

2014
/**

api-extractor/testInputs/example3/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ declare const packageDescription: void;
55

66
export {
77
inheritLocalOptionOne,
8-
inheritLocalOptionTwo,
9-
inheritLocalOptionThreeFunction,
8+
inheritLocalOptionTwoFunction,
109
inheritEnumValues,
1110
sourceEnumValuesDoc,
1211
inheritLocalCircularDependencyOne,

0 commit comments

Comments
 (0)