Skip to content

Commit 845b291

Browse files
authored
Stub TestCoverage API (#13631)
contributed on behalf of STMicroelectronics Signed-off-by: Remi Schnekenburger <[email protected]>
1 parent 1578d2d commit 845b291

File tree

5 files changed

+280
-2
lines changed

5 files changed

+280
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
## not yet released
88

99
- [scm] added support for dirty diff peek view [#13104](https://github.com/eclipse-theia/theia/pull/13104)
10+
- [test] stub VS Code `Test Coverage` API [#13631](https://github.com/eclipse-theia/theia/pull/13631)
1011

1112
<a name="breaking_changes_not_yet_released">[Breaking Changes:](#breaking_changes_not_yet_released)</a>
1213
- [scm] revised some of the dirty diff related types [#13104](https://github.com/eclipse-theia/theia/pull/13104)

packages/plugin-ext/src/plugin/plugin-context.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,12 @@ import {
203203
TerminalOutputAnchor,
204204
TerminalQuickFixTerminalCommand,
205205
TerminalQuickFixOpener,
206-
TestResultState
206+
TestResultState,
207+
BranchCoverage,
208+
DeclarationCoverage,
209+
FileCoverage,
210+
StatementCoverage,
211+
TestCoverageCount
207212
} from './types-impl';
208213
import { AuthenticationExtImpl } from './authentication-ext';
209214
import { SymbolKind } from '../common/plugin-api-rpc-model';
@@ -1402,7 +1407,12 @@ export function createAPIFactory(
14021407
TerminalQuickFixTerminalCommand,
14031408
TerminalQuickFixOpener,
14041409
EditSessionIdentityMatch,
1405-
TestResultState
1410+
TestResultState,
1411+
BranchCoverage,
1412+
DeclarationCoverage,
1413+
FileCoverage,
1414+
StatementCoverage,
1415+
TestCoverageCount
14061416
};
14071417
};
14081418
}

packages/plugin-ext/src/plugin/tests.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ class TestRun implements theia.TestRun {
240240
onDidEnd: Event<void> = this.onDidEndEmitter.event;
241241
private onWillFlushEmitter = new Emitter<void>();
242242
onWillFlush: Event<void> = this.onWillFlushEmitter.event;
243+
private onDidDisposeEmitter = new Emitter<void>();
244+
onDidDispose: Event<void> = this.onDidDisposeEmitter.event;
243245

244246
readonly id: string;
245247
private testStateDeltas = new Map<theia.TestItem, TestStateChangeDTO>();
@@ -293,6 +295,9 @@ class TestRun implements theia.TestRun {
293295
this.proxy.$notifyTestRunEnded(this.controller.id, this.id);
294296
}
295297

298+
/** @stubbed */
299+
addCoverage(fileCoverage: theia.FileCoverage): void { }
300+
296301
private checkNotEnded(test: theia.TestItem): boolean {
297302
if (this.ended) {
298303
console.warn(`Setting the state of test "${test.id}" is a no - op after the run ends.`);

packages/plugin-ext/src/plugin/types-impl.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3330,6 +3330,72 @@ export class TestMessage implements theia.TestMessage {
33303330
constructor(public message: string | theia.MarkdownString) { }
33313331
}
33323332

3333+
@es5ClassCompat
3334+
export class TestCoverageCount {
3335+
constructor( public covered: number, public total: number) { }
3336+
}
3337+
3338+
@es5ClassCompat
3339+
export class FileCoverage {
3340+
3341+
detailedCoverage?: theia.FileCoverageDetail[];
3342+
3343+
static fromDetails(uri: theia.Uri, details: theia.FileCoverageDetail[]): FileCoverage {
3344+
const statements = new TestCoverageCount(0, 0);
3345+
const branches = new TestCoverageCount(0, 0);
3346+
const decl = new TestCoverageCount(0, 0);
3347+
3348+
for (const detail of details) {
3349+
if (detail instanceof StatementCoverage) {
3350+
statements.total += 1;
3351+
statements.covered += detail.executed ? 1 : 0;
3352+
3353+
for (const branch of detail.branches) {
3354+
branches.total += 1;
3355+
branches.covered += branch.executed ? 1 : 0;
3356+
}
3357+
} else {
3358+
decl.total += 1;
3359+
decl.covered += detail.executed ? 1 : 0;
3360+
}
3361+
}
3362+
3363+
const coverage = new FileCoverage(
3364+
uri,
3365+
statements,
3366+
branches.total > 0 ? branches : undefined,
3367+
decl.total > 0 ? decl : undefined,
3368+
);
3369+
3370+
coverage.detailedCoverage = details;
3371+
3372+
return coverage;
3373+
}
3374+
3375+
constructor(
3376+
public uri: theia.Uri,
3377+
public statementCoverage: TestCoverageCount,
3378+
public branchCoverage?: TestCoverageCount,
3379+
public declarationCoverage?: TestCoverageCount,
3380+
) { }
3381+
}
3382+
3383+
@es5ClassCompat
3384+
export class StatementCoverage implements theia.StatementCoverage {
3385+
constructor(public executed: number | boolean, public location: Position | Range, public branches: BranchCoverage[] = []) { }
3386+
}
3387+
3388+
export class BranchCoverage implements theia.BranchCoverage {
3389+
constructor(public executed: number | boolean, public location?: Position | Range, public label?: string) { }
3390+
}
3391+
3392+
@es5ClassCompat
3393+
export class DeclarationCoverage implements theia.DeclarationCoverage {
3394+
constructor(public name: string, public executed: number | boolean, public location: Position | Range) { }
3395+
}
3396+
3397+
export type FileCoverageDetail = StatementCoverage | DeclarationCoverage;
3398+
33333399
@es5ClassCompat
33343400
export class TimelineItem {
33353401
timestamp: number;

packages/plugin/src/theia.d.ts

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16035,6 +16035,18 @@ export module '@theia/plugin' {
1603516035
*/
1603616036
runHandler: (request: TestRunRequest, token: CancellationToken) => Thenable<void> | void;
1603716037

16038+
/**
16039+
* An extension-provided function that provides detailed statement and
16040+
* function-level coverage for a file. The editor will call this when more
16041+
* detail is needed for a file, such as when it's opened in an editor or
16042+
* expanded in the **Test Coverage** view.
16043+
*
16044+
* The {@link FileCoverage} object passed to this function is the same instance
16045+
* emitted on {@link TestRun.addCoverage} calls associated with this profile.
16046+
* @stubbed
16047+
*/
16048+
loadDetailedCoverage?: (testRun: TestRun, fileCoverage: FileCoverage, token: CancellationToken) => Thenable<FileCoverageDetail[]>;
16049+
1603816050
/**
1603916051
* Deletes the run profile.
1604016052
*/
@@ -16314,11 +16326,23 @@ export module '@theia/plugin' {
1631416326
*/
1631516327
appendOutput(output: string, location?: Location, test?: TestItem): void;
1631616328

16329+
/**
16330+
* Adds coverage for a file in the run.
16331+
* @stubbed
16332+
*/
16333+
addCoverage(fileCoverage: FileCoverage): void;
16334+
1631716335
/**
1631816336
* Signals the end of the test run. Any tests included in the run whose
1631916337
* states have not been updated will have their state reset.
1632016338
*/
1632116339
end(): void;
16340+
16341+
/**
16342+
* An event fired when the editor is no longer interested in data
16343+
* associated with the test run.
16344+
*/
16345+
onDidDispose: Event<void>;
1632216346
}
1632316347

1632416348
/**
@@ -16527,6 +16551,178 @@ export module '@theia/plugin' {
1652716551
*/
1652816552
constructor(message: string | MarkdownString);
1652916553
}
16554+
16555+
/**
16556+
* A class that contains information about a covered resource. A count can
16557+
* be give for lines, branches, and declarations in a file.
16558+
*/
16559+
export class TestCoverageCount {
16560+
/**
16561+
* Number of items covered in the file.
16562+
*/
16563+
covered: number;
16564+
/**
16565+
* Total number of covered items in the file.
16566+
*/
16567+
total: number;
16568+
16569+
/**
16570+
* @param covered Value for {@link TestCoverageCount.covered}
16571+
* @param total Value for {@link TestCoverageCount.total}
16572+
*/
16573+
constructor(covered: number, total: number);
16574+
}
16575+
16576+
/**
16577+
* Contains coverage metadata for a file.
16578+
*/
16579+
export class FileCoverage {
16580+
/**
16581+
* File URI.
16582+
*/
16583+
readonly uri: Uri;
16584+
16585+
/**
16586+
* Statement coverage information. If the reporter does not provide statement
16587+
* coverage information, this can instead be used to represent line coverage.
16588+
*/
16589+
statementCoverage: TestCoverageCount;
16590+
16591+
/**
16592+
* Branch coverage information.
16593+
*/
16594+
branchCoverage?: TestCoverageCount;
16595+
16596+
/**
16597+
* Declaration coverage information. Depending on the reporter and
16598+
* language, this may be types such as functions, methods, or namespaces.
16599+
*/
16600+
declarationCoverage?: TestCoverageCount;
16601+
16602+
/**
16603+
* Creates a {@link FileCoverage} instance with counts filled in from
16604+
* the coverage details.
16605+
* @param uri Covered file URI
16606+
* @param detailed Detailed coverage information
16607+
*/
16608+
static fromDetails(uri: Uri, details: readonly FileCoverageDetail[]): FileCoverage;
16609+
16610+
/**
16611+
* @param uri Covered file URI
16612+
* @param statementCoverage Statement coverage information. If the reporter
16613+
* does not provide statement coverage information, this can instead be
16614+
* used to represent line coverage.
16615+
* @param branchCoverage Branch coverage information
16616+
* @param declarationCoverage Declaration coverage information
16617+
*/
16618+
constructor(
16619+
uri: Uri,
16620+
statementCoverage: TestCoverageCount,
16621+
branchCoverage?: TestCoverageCount,
16622+
declarationCoverage?: TestCoverageCount,
16623+
);
16624+
}
16625+
16626+
/**
16627+
* Contains coverage information for a single statement or line.
16628+
*/
16629+
export class StatementCoverage {
16630+
/**
16631+
* The number of times this statement was executed, or a boolean indicating
16632+
* whether it was executed if the exact count is unknown. If zero or false,
16633+
* the statement will be marked as un-covered.
16634+
*/
16635+
executed: number | boolean;
16636+
16637+
/**
16638+
* Statement location.
16639+
*/
16640+
location: Position | Range;
16641+
16642+
/**
16643+
* Coverage from branches of this line or statement. If it's not a
16644+
* conditional, this will be empty.
16645+
*/
16646+
branches: BranchCoverage[];
16647+
16648+
/**
16649+
* @param location The statement position.
16650+
* @param executed The number of times this statement was executed, or a
16651+
* boolean indicating whether it was executed if the exact count is
16652+
* unknown. If zero or false, the statement will be marked as un-covered.
16653+
* @param branches Coverage from branches of this line. If it's not a
16654+
* conditional, this should be omitted.
16655+
*/
16656+
constructor(executed: number | boolean, location: Position | Range, branches?: BranchCoverage[]);
16657+
}
16658+
16659+
/**
16660+
* Contains coverage information for a branch of a {@link StatementCoverage}.
16661+
*/
16662+
export class BranchCoverage {
16663+
/**
16664+
* The number of times this branch was executed, or a boolean indicating
16665+
* whether it was executed if the exact count is unknown. If zero or false,
16666+
* the branch will be marked as un-covered.
16667+
*/
16668+
executed: number | boolean;
16669+
16670+
/**
16671+
* Branch location.
16672+
*/
16673+
location?: Position | Range;
16674+
16675+
/**
16676+
* Label for the branch, used in the context of "the ${label} branch was
16677+
* not taken," for example.
16678+
*/
16679+
label?: string;
16680+
16681+
/**
16682+
* @param executed The number of times this branch was executed, or a
16683+
* boolean indicating whether it was executed if the exact count is
16684+
* unknown. If zero or false, the branch will be marked as un-covered.
16685+
* @param location The branch position.
16686+
*/
16687+
constructor(executed: number | boolean, location?: Position | Range, label?: string);
16688+
}
16689+
16690+
/**
16691+
* Contains coverage information for a declaration. Depending on the reporter
16692+
* and language, this may be types such as functions, methods, or namespaces.
16693+
*/
16694+
export class DeclarationCoverage {
16695+
/**
16696+
* Name of the declaration.
16697+
*/
16698+
name: string;
16699+
16700+
/**
16701+
* The number of times this declaration was executed, or a boolean
16702+
* indicating whether it was executed if the exact count is unknown. If
16703+
* zero or false, the declaration will be marked as un-covered.
16704+
*/
16705+
executed: number | boolean;
16706+
16707+
/**
16708+
* Declaration location.
16709+
*/
16710+
location: Position | Range;
16711+
16712+
/**
16713+
* @param executed The number of times this declaration was executed, or a
16714+
* boolean indicating whether it was executed if the exact count is
16715+
* unknown. If zero or false, the declaration will be marked as un-covered.
16716+
* @param location The declaration position.
16717+
*/
16718+
constructor(name: string, executed: number | boolean, location: Position | Range);
16719+
}
16720+
16721+
/**
16722+
* Coverage details returned from {@link TestRunProfile.loadDetailedCoverage}.
16723+
*/
16724+
export type FileCoverageDetail = StatementCoverage | DeclarationCoverage;
16725+
1653016726
/**
1653116727
* Thenable is a common denominator between ES6 promises, Q, jquery.Deferred, WinJS.Promise,
1653216728
* and others. This API makes no assumption about what promise library is being used which

0 commit comments

Comments
 (0)