Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stub TestCoverage API #13631

Merged
merged 1 commit into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
## not yet released

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

<a name="breaking_changes_not_yet_released">[Breaking Changes:](#breaking_changes_not_yet_released)</a>
- [scm] revised some of the dirty diff related types [#13104](https://github.com/eclipse-theia/theia/pull/13104)
Expand Down
14 changes: 12 additions & 2 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,12 @@ import {
TerminalOutputAnchor,
TerminalQuickFixTerminalCommand,
TerminalQuickFixOpener,
TestResultState
TestResultState,
BranchCoverage,
DeclarationCoverage,
FileCoverage,
StatementCoverage,
TestCoverageCount
} from './types-impl';
import { AuthenticationExtImpl } from './authentication-ext';
import { SymbolKind } from '../common/plugin-api-rpc-model';
Expand Down Expand Up @@ -1402,7 +1407,12 @@ export function createAPIFactory(
TerminalQuickFixTerminalCommand,
TerminalQuickFixOpener,
EditSessionIdentityMatch,
TestResultState
TestResultState,
BranchCoverage,
DeclarationCoverage,
FileCoverage,
StatementCoverage,
TestCoverageCount
};
};
}
Expand Down
5 changes: 5 additions & 0 deletions packages/plugin-ext/src/plugin/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ class TestRun implements theia.TestRun {
onDidEnd: Event<void> = this.onDidEndEmitter.event;
private onWillFlushEmitter = new Emitter<void>();
onWillFlush: Event<void> = this.onWillFlushEmitter.event;
private onDidDisposeEmitter = new Emitter<void>();
onDidDispose: Event<void> = this.onDidDisposeEmitter.event;

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

/** @stubbed */
addCoverage(fileCoverage: theia.FileCoverage): void { }

private checkNotEnded(test: theia.TestItem): boolean {
if (this.ended) {
console.warn(`Setting the state of test "${test.id}" is a no - op after the run ends.`);
Expand Down
66 changes: 66 additions & 0 deletions packages/plugin-ext/src/plugin/types-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3330,6 +3330,72 @@ export class TestMessage implements theia.TestMessage {
constructor(public message: string | theia.MarkdownString) { }
}

@es5ClassCompat
export class TestCoverageCount {
constructor( public covered: number, public total: number) { }
}

@es5ClassCompat
export class FileCoverage {

detailedCoverage?: theia.FileCoverageDetail[];

static fromDetails(uri: theia.Uri, details: theia.FileCoverageDetail[]): FileCoverage {
const statements = new TestCoverageCount(0, 0);
const branches = new TestCoverageCount(0, 0);
const decl = new TestCoverageCount(0, 0);

for (const detail of details) {
if (detail instanceof StatementCoverage) {
statements.total += 1;
statements.covered += detail.executed ? 1 : 0;

for (const branch of detail.branches) {
branches.total += 1;
branches.covered += branch.executed ? 1 : 0;
}
} else {
decl.total += 1;
decl.covered += detail.executed ? 1 : 0;
}
}

const coverage = new FileCoverage(
uri,
statements,
branches.total > 0 ? branches : undefined,
decl.total > 0 ? decl : undefined,
);

coverage.detailedCoverage = details;

return coverage;
}

constructor(
public uri: theia.Uri,
public statementCoverage: TestCoverageCount,
public branchCoverage?: TestCoverageCount,
public declarationCoverage?: TestCoverageCount,
) { }
}

@es5ClassCompat
export class StatementCoverage implements theia.StatementCoverage {
constructor(public executed: number | boolean, public location: Position | Range, public branches: BranchCoverage[] = []) { }
}

export class BranchCoverage implements theia.BranchCoverage {
constructor(public executed: number | boolean, public location?: Position | Range, public label?: string) { }
}

@es5ClassCompat
export class DeclarationCoverage implements theia.DeclarationCoverage {
constructor(public name: string, public executed: number | boolean, public location: Position | Range) { }
}

export type FileCoverageDetail = StatementCoverage | DeclarationCoverage;

@es5ClassCompat
export class TimelineItem {
timestamp: number;
Expand Down
196 changes: 196 additions & 0 deletions packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16035,6 +16035,18 @@ export module '@theia/plugin' {
*/
runHandler: (request: TestRunRequest, token: CancellationToken) => Thenable<void> | void;

/**
* An extension-provided function that provides detailed statement and
* function-level coverage for a file. The editor will call this when more
* detail is needed for a file, such as when it's opened in an editor or
* expanded in the **Test Coverage** view.
*
* The {@link FileCoverage} object passed to this function is the same instance
* emitted on {@link TestRun.addCoverage} calls associated with this profile.
* @stubbed
*/
loadDetailedCoverage?: (testRun: TestRun, fileCoverage: FileCoverage, token: CancellationToken) => Thenable<FileCoverageDetail[]>;

/**
* Deletes the run profile.
*/
Expand Down Expand Up @@ -16314,11 +16326,23 @@ export module '@theia/plugin' {
*/
appendOutput(output: string, location?: Location, test?: TestItem): void;

/**
* Adds coverage for a file in the run.
* @stubbed
*/
addCoverage(fileCoverage: FileCoverage): void;

/**
* Signals the end of the test run. Any tests included in the run whose
* states have not been updated will have their state reset.
*/
end(): void;

/**
* An event fired when the editor is no longer interested in data
* associated with the test run.
*/
onDidDispose: Event<void>;
}

/**
Expand Down Expand Up @@ -16527,6 +16551,178 @@ export module '@theia/plugin' {
*/
constructor(message: string | MarkdownString);
}

/**
* A class that contains information about a covered resource. A count can
* be give for lines, branches, and declarations in a file.
*/
export class TestCoverageCount {
/**
* Number of items covered in the file.
*/
covered: number;
/**
* Total number of covered items in the file.
*/
total: number;

/**
* @param covered Value for {@link TestCoverageCount.covered}
* @param total Value for {@link TestCoverageCount.total}
*/
constructor(covered: number, total: number);
}

/**
* Contains coverage metadata for a file.
*/
export class FileCoverage {
/**
* File URI.
*/
readonly uri: Uri;

/**
* Statement coverage information. If the reporter does not provide statement
* coverage information, this can instead be used to represent line coverage.
*/
statementCoverage: TestCoverageCount;

/**
* Branch coverage information.
*/
branchCoverage?: TestCoverageCount;

/**
* Declaration coverage information. Depending on the reporter and
* language, this may be types such as functions, methods, or namespaces.
*/
declarationCoverage?: TestCoverageCount;

/**
* Creates a {@link FileCoverage} instance with counts filled in from
* the coverage details.
* @param uri Covered file URI
* @param detailed Detailed coverage information
*/
static fromDetails(uri: Uri, details: readonly FileCoverageDetail[]): FileCoverage;

/**
* @param uri Covered file URI
* @param statementCoverage Statement coverage information. If the reporter
* does not provide statement coverage information, this can instead be
* used to represent line coverage.
* @param branchCoverage Branch coverage information
* @param declarationCoverage Declaration coverage information
*/
constructor(
uri: Uri,
statementCoverage: TestCoverageCount,
branchCoverage?: TestCoverageCount,
declarationCoverage?: TestCoverageCount,
);
}

/**
* Contains coverage information for a single statement or line.
*/
export class StatementCoverage {
/**
* The number of times this statement was executed, or a boolean indicating
* whether it was executed if the exact count is unknown. If zero or false,
* the statement will be marked as un-covered.
*/
executed: number | boolean;

/**
* Statement location.
*/
location: Position | Range;

/**
* Coverage from branches of this line or statement. If it's not a
* conditional, this will be empty.
*/
branches: BranchCoverage[];

/**
* @param location The statement position.
* @param executed The number of times this statement was executed, or a
* boolean indicating whether it was executed if the exact count is
* unknown. If zero or false, the statement will be marked as un-covered.
* @param branches Coverage from branches of this line. If it's not a
* conditional, this should be omitted.
*/
constructor(executed: number | boolean, location: Position | Range, branches?: BranchCoverage[]);
}

/**
* Contains coverage information for a branch of a {@link StatementCoverage}.
*/
export class BranchCoverage {
/**
* The number of times this branch was executed, or a boolean indicating
* whether it was executed if the exact count is unknown. If zero or false,
* the branch will be marked as un-covered.
*/
executed: number | boolean;

/**
* Branch location.
*/
location?: Position | Range;

/**
* Label for the branch, used in the context of "the ${label} branch was
* not taken," for example.
*/
label?: string;

/**
* @param executed The number of times this branch was executed, or a
* boolean indicating whether it was executed if the exact count is
* unknown. If zero or false, the branch will be marked as un-covered.
* @param location The branch position.
*/
constructor(executed: number | boolean, location?: Position | Range, label?: string);
}

/**
* Contains coverage information for a declaration. Depending on the reporter
* and language, this may be types such as functions, methods, or namespaces.
*/
export class DeclarationCoverage {
/**
* Name of the declaration.
*/
name: string;

/**
* The number of times this declaration was executed, or a boolean
* indicating whether it was executed if the exact count is unknown. If
* zero or false, the declaration will be marked as un-covered.
*/
executed: number | boolean;

/**
* Declaration location.
*/
location: Position | Range;

/**
* @param executed The number of times this declaration was executed, or a
* boolean indicating whether it was executed if the exact count is
* unknown. If zero or false, the declaration will be marked as un-covered.
* @param location The declaration position.
*/
constructor(name: string, executed: number | boolean, location: Position | Range);
}

/**
* Coverage details returned from {@link TestRunProfile.loadDetailedCoverage}.
*/
export type FileCoverageDetail = StatementCoverage | DeclarationCoverage;

/**
* Thenable is a common denominator between ES6 promises, Q, jquery.Deferred, WinJS.Promise,
* and others. This API makes no assumption about what promise library is being used which
Expand Down
Loading