problemMatcher.ts ×64

Frontier kind: Code frontier

unlabeled · c_ebe65a34b085

83 tests · 12366 LOC · 50 files · introduces 0 tests · 1260 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
77 ranges1260 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1190 ranges12366 lines · 50 files · Browse complete extent
All tests (intent)
83 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 1260 introduced LOC across 77 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/tasks/common/problemMatcher.ts 1207 introduced LOC · 64 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- problemMatcher.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { localize } from '../../../../nls.js';
7 >
8 > import * as Objects from '../../../../base/common/objects.js';
9 > import * as Strings from '../../../../base/common/strings.js';
10 > import * as Assert from '../../../../base/common/assert.js';
11 > import { join, normalize } from '../../../../base/common/path.js';
12 > import * as Types from '../../../../base/common/types.js';
13 > import * as UUID from '../../../../base/common/uuid.js';
14 > import * as Platform from '../../../../base/common/platform.js';
15 > import Severity from '../../../../base/common/severity.js';
16 > import { URI } from '../../../../base/common/uri.js';
17 > import { IJSONSchema } from '../../../../base/common/jsonSchema.js';
18 > import { ValidationStatus, ValidationState, IProblemReporter, Parser } from '../../../../base/common/parsers.js';
19 > import { IStringDictionary } from '../../../../base/common/collections.js';
20 > import { asArray } from '../../../../base/common/arrays.js';
21 > import { Schemas as NetworkSchemas } from '../../../../base/common/network.js';
22 >
23 > import { IMarkerData, MarkerSeverity } from '../../../../platform/markers/common/markers.js';
24 > import { ExtensionsRegistry, ExtensionMessageCollector } from '../../../services/extensions/common/extensionsRegistry.js';
25 > import { Event, Emitter } from '../../../../base/common/event.js';
26 > import { FileType, IFileService, IFileStatWithPartialMetadata, IFileSystemProvider } from '../../../../platform/files/common/files.js';
27 > import { ILogService } from '../../../../platform/log/common/log.js';
28 >
29 > export enum FileLocationKind {
30 > Default,
31 > Relative,
32 > Absolute,
33 > AutoDetect,
34 > Search
35 > }
36 >
37 > export namespace FileLocationKind {
38 > export function fromString(value: string): FileLocationKind | undefined {
39 value = value.toLowerCase();
40 if (value === 'absolute') {
50 }
51 }
53 >
54 > export enum ProblemLocationKind {
55 > File,
56 > Location
57 > }
58 >
59 > export namespace ProblemLocationKind {
60 > export function fromString(value: string): ProblemLocationKind | undefined {
61 value = value.toLowerCase();
62 if (value === 'file') {
68 }
69 }
71 >
72 > export interface IProblemPattern {
73 > regexp: RegExp;
74 >
75 > kind?: ProblemLocationKind;
76 >
77 > file?: number;
78 >
79 > message?: number;
80 >
81 > location?: number;
82 >
83 > line?: number;
84 >
85 > character?: number;
86 >
87 > endLine?: number;
88 >
89 > endCharacter?: number;
90 >
91 > code?: number;
92 >
93 > severity?: number;
94 >
95 > loop?: boolean;
96 > }
97 >
98 > export interface INamedProblemPattern extends IProblemPattern {
99 > name: string;
100 > }
101 >
102 > export type MultiLineProblemPattern = IProblemPattern[];
103 >
104 > export interface IWatchingPattern {
105 > regexp: RegExp;
106 > file?: number;
107 > }
108 >
109 > export interface IWatchingMatcher {
110 > activeOnStart: boolean;
111 > beginsPattern: IWatchingPattern;
112 > endsPattern: IWatchingPattern;
113 > }
114 >
115 > export enum ApplyToKind {
116 > allDocuments,
117 > openDocuments,
118 > closedDocuments
119 > }
120 >
121 > export namespace ApplyToKind {
122 > export function fromString(value: string): ApplyToKind | undefined {
123 value = value.toLowerCase();
124 if (value === 'alldocuments') {
132 }
133 }
135 >
136 > export interface ProblemMatcher {
137 > owner: string;
138 > source?: string;
139 > applyTo: ApplyToKind;
140 > fileLocation: FileLocationKind;
141 > filePrefix?: string | Config.SearchFileLocationArgs;
142 > pattern: Types.SingleOrMany<IProblemPattern>;
143 > severity?: Severity;
144 > watching?: IWatchingMatcher;
145 > uriProvider?: (path: string) => URI;
146 > }
147 >
148 > export interface INamedProblemMatcher extends ProblemMatcher {
149 > name: string;
150 > label: string;
151 > deprecated?: boolean;
152 > }
153 >
154 > export interface INamedMultiLineProblemPattern {
155 > name: string;
156 > label: string;
157 > patterns: MultiLineProblemPattern;
158 > }
159 >
160 > export function isNamedProblemMatcher(value: ProblemMatcher | undefined): value is INamedProblemMatcher {
161 return value && Types.isString((<INamedProblemMatcher>value).name) ? true : false;
162 }
164 > interface ILocation {
165 > startLineNumber: number;
166 > startCharacter: number;
167 > endLineNumber: number;
168 > endCharacter: number;
169 > }
170 >
171 > interface IProblemData {
172 > kind?: ProblemLocationKind;
173 > file?: string;
174 > location?: string;
175 > line?: string;
176 > character?: string;
177 > endLine?: string;
178 > endCharacter?: string;
179 > message?: string;
180 > severity?: string;
181 > code?: string;
182 > }
183 >
184 > export interface IProblemMatch {
185 > resource: Promise<URI>;
186 > marker: IMarkerData;
187 > description: ProblemMatcher;
188 > }
189 >
190 > export interface IHandleResult {
191 > match: IProblemMatch | null;
192 > continue: boolean;
193 > }
194 >
195 >
196 export async function getResource(filename: string, matcher: ProblemMatcher, fileService?: IFileService): Promise<URI> {
197 const kind = matcher.fileLocation;
246 }
247 }
249 async function searchForFileLocation(filename: string, fsProvider: IFileSystemProvider, args: Config.SearchFileLocationArgs): Promise<URI | undefined> {
250 const exclusions = new Set(asArray(args.exclude || []).map(x => URI.file(x).path));
296 return undefined;
297 }
299 > export interface ILineMatcher {
300 > matchLength: number;
301 > next(line: string): IProblemMatch | null;
302 > handle(lines: string[], start?: number): IHandleResult;
303 > }
304 >
305 > export function createLineMatcher(matcher: ProblemMatcher, fileService?: IFileService, logService?: ILogService): ILineMatcher {
306 const pattern = matcher.pattern;
307 if (Array.isArray(pattern)) {
311 }
312 }
314 > const endOfLine: string = Platform.OS === Platform.OperatingSystem.Windows ? '\r\n' : '\n';
315 >
316 > abstract class AbstractLineMatcher implements ILineMatcher {
317 > private matcher: ProblemMatcher;
318 > private fileService?: IFileService;
319 > private logService?: ILogService;
320 >
321 > constructor(matcher: ProblemMatcher, fileService?: IFileService, logService?: ILogService) {
322 this.matcher = matcher;
323 this.fileService = fileService;
324 this.logService = logService;
325 }
327 > public handle(lines: string[], start: number = 0): IHandleResult {
328 return { match: null, continue: false };
329 }
331 > public next(line: string): IProblemMatch | null {
332 return null;
333 }
335 > public abstract get matchLength(): number;
336 >
337 > protected regexpExec(regexp: RegExp, line: string): RegExpExecArray | null {
338 const start = Date.now();
339 const result = regexp.exec(line);
344 return result;
345 }
347 > protected fillProblemData(data: IProblemData | undefined, pattern: IProblemPattern, matches: RegExpExecArray): data is IProblemData {
348 if (data) {
349 this.fillProperty(data, 'file', pattern, matches, true);
361 }
362 }
364 > private appendProperty(data: IProblemData, property: keyof IProblemData, pattern: IProblemPattern, matches: RegExpExecArray, trim: boolean = false): void {
365 const patternProperty = pattern[property];
366 if (Types.isUndefined(data[property])) {
375 }
376 }
378 > private fillProperty(data: IProblemData, property: keyof IProblemData, pattern: IProblemPattern, matches: RegExpExecArray, trim: boolean = false): void {
379 const patternAtProperty = pattern[property];
380 if (Types.isUndefined(data[property]) && !Types.isUndefined(patternAtProperty) && patternAtProperty < matches.length) {
388 }
389 }
391 > protected getMarkerMatch(data: IProblemData): IProblemMatch | undefined {
392 try {
393 const location = this.getLocation(data);
418 return undefined;
419 }
421 > protected getResource(filename: string): Promise<URI> {
422 return getResource(filename, this.matcher, this.fileService);
423 }
425 > private getLocation(data: IProblemData): ILocation | null {
426 if (data.kind === ProblemLocationKind.File) {
427 return this.createLocation(0, 0, 0, 0);
439 return this.createLocation(startLine, startColumn, endLine, endColumn);
440 }
442 > private parseLocationInfo(value: string): ILocation | null {
443 if (!value || !value.match(/(\d+|\d+,\d+|\d+,\d+,\d+,\d+)/)) {
444 return null;
453 }
454 }
456 > private createLocation(startLine: number, startColumn: number | undefined, endLine: number | undefined, endColumn: number | undefined): ILocation {
457 if (startColumn !== undefined && endColumn !== undefined) {
458 return { startLineNumber: startLine, startCharacter: startColumn, endLineNumber: endLine || startLine, endCharacter: endColumn };
463 return { startLineNumber: startLine, startCharacter: 1, endLineNumber: startLine, endCharacter: 2 ** 31 - 1 }; // See https://github.com/microsoft/vscode/issues/80288#issuecomment-650636442 for discussion
464 }
466 > private getSeverity(data: IProblemData): MarkerSeverity {
467 let result: Severity | null = null;
468 if (data.severity) {
490 return MarkerSeverity.fromSeverity(result);
491 }
493 >
494 > class SingleLineMatcher extends AbstractLineMatcher {
495 >
496 > private pattern: IProblemPattern;
497 >
498 > constructor(matcher: ProblemMatcher, fileService?: IFileService, logService?: ILogService) {
499 super(matcher, fileService, logService);
500 this.pattern = <IProblemPattern>matcher.pattern;
501 }
503 > public get matchLength(): number {
504 return 1;
505 }
507 > public override handle(lines: string[], start: number = 0): IHandleResult {
508 Assert.ok(lines.length - start === 1);
509 const data: IProblemData = Object.create(null);
524 return { match: null, continue: false };
525 }
527 > public override next(line: string): IProblemMatch | null {
528 return null;
529 }
531 >
532 > class MultiLineMatcher extends AbstractLineMatcher {
533 >
534 > private patterns: IProblemPattern[];
535 > private data: IProblemData | undefined;
536 >
537 > constructor(matcher: ProblemMatcher, fileService?: IFileService, logService?: ILogService) {
538 super(matcher, fileService, logService);
539 this.patterns = <IProblemPattern[]>matcher.pattern;
540 }
542 > public get matchLength(): number {
543 return this.patterns.length;
544 }
546 > public override handle(lines: string[], start: number = 0): IHandleResult {
547 Assert.ok(lines.length - start === this.patterns.length);
548 this.data = Object.create(null);
569 return { match: markerMatch ? markerMatch : null, continue: loop };
570 }
572 > public override next(line: string): IProblemMatch | null {
573 const pattern = this.patterns[this.patterns.length - 1];
574 Assert.ok(pattern.loop === true && this.data !== null);
585 return problemMatch ? problemMatch : null;
586 }
588 >
589 > export namespace Config {
590 >
591 > export interface IProblemPattern {
592 >
593 > /**
594 > * The regular expression to find a problem in the console output of an
595 > * executed task.
596 > */
597 > regexp?: string;
598 >
599 > /**
600 > * Whether the pattern matches a whole file, or a location (file/line)
601 > *
602 > * The default is to match for a location. Only valid on the
603 > * first problem pattern in a multi line problem matcher.
604 > */
605 > kind?: string;
606 >
607 > /**
608 > * The match group index of the filename.
609 > * If omitted 1 is used.
610 > */
611 > file?: number;
612 >
613 > /**
614 > * The match group index of the problem's location. Valid location
615 > * patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn).
616 > * If omitted the line and column properties are used.
617 > */
618 > location?: number;
619 >
620 > /**
621 > * The match group index of the problem's line in the source file.
622 > *
623 > * Defaults to 2.
624 > */
625 > line?: number;
626 >
627 > /**
628 > * The match group index of the problem's column in the source file.
629 > *
630 > * Defaults to 3.
631 > */
632 > column?: number;
633 >
634 > /**
635 > * The match group index of the problem's end line in the source file.
636 > *
637 > * Defaults to undefined. No end line is captured.
638 > */
639 > endLine?: number;
640 >
641 > /**
642 > * The match group index of the problem's end column in the source file.
643 > *
644 > * Defaults to undefined. No end column is captured.
645 > */
646 > endColumn?: number;
647 >
648 > /**
649 > * The match group index of the problem's severity.
650 > *
651 > * Defaults to undefined. In this case the problem matcher's severity
652 > * is used.
653 > */
654 > severity?: number;
655 >
656 > /**
657 > * The match group index of the problem's code.
658 > *
659 > * Defaults to undefined. No code is captured.
660 > */
661 > code?: number;
662 >
663 > /**
664 > * The match group index of the message. If omitted it defaults
665 > * to 4 if location is specified. Otherwise it defaults to 5.
666 > */
667 > message?: number;
668 >
669 > /**
670 > * Specifies if the last pattern in a multi line problem matcher should
671 > * loop as long as it does match a line consequently. Only valid on the
672 > * last problem pattern in a multi line problem matcher.
673 > */
674 > loop?: boolean;
675 > }
676 >
677 > export interface ICheckedProblemPattern extends IProblemPattern {
678 > /**
679 > * The regular expression to find a problem in the console output of an
680 > * executed task.
681 > */
682 > regexp: string;
683 > }
684 >
685 > export namespace CheckedProblemPattern {
686 > export function is(value: unknown): value is ICheckedProblemPattern {
687 const candidate: IProblemPattern = value as IProblemPattern;
688 return candidate && Types.isString(candidate.regexp);
689 }
691 >
692 > export interface INamedProblemPattern extends IProblemPattern {
693 > /**
694 > * The name of the problem pattern.
695 > */
696 > name: string;
697 >
698 > /**
699 > * A human readable label
700 > */
701 > label?: string;
702 > }
703 >
704 > export namespace NamedProblemPattern {
705 > export function is(value: unknown): value is INamedProblemPattern {
706 const candidate: INamedProblemPattern = value as INamedProblemPattern;
707 return candidate && Types.isString(candidate.name);
708 }
710 >
711 > export interface INamedCheckedProblemPattern extends INamedProblemPattern {
712 > /**
713 > * The regular expression to find a problem in the console output of an
714 > * executed task.
715 > */
716 > regexp: string;
717 > }
718 >
719 > export namespace NamedCheckedProblemPattern {
720 > export function is(value: unknown): value is INamedCheckedProblemPattern {
721 const candidate: INamedProblemPattern = value as INamedProblemPattern;
722 return candidate && NamedProblemPattern.is(candidate) && Types.isString(candidate.regexp);
723 }
725 >
726 > export type MultiLineProblemPattern = IProblemPattern[];
727 >
728 > export namespace MultiLineProblemPattern {
729 > export function is(value: unknown): value is MultiLineProblemPattern {
730 return Array.isArray(value);
731 }
733 >
734 > export type MultiLineCheckedProblemPattern = ICheckedProblemPattern[];
735 >
736 > export namespace MultiLineCheckedProblemPattern {
737 > export function is(value: unknown): value is MultiLineCheckedProblemPattern {
738 if (!MultiLineProblemPattern.is(value)) {
739 return false;
746 return true;
747 }
749 >
750 > export interface INamedMultiLineCheckedProblemPattern {
751 > /**
752 > * The name of the problem pattern.
753 > */
754 > name: string;
755 >
756 > /**
757 > * A human readable label
758 > */
759 > label?: string;
760 >
761 > /**
762 > * The actual patterns
763 > */
764 > patterns: MultiLineCheckedProblemPattern;
765 > }
766 >
767 > export namespace NamedMultiLineCheckedProblemPattern {
768 > export function is(value: unknown): value is INamedMultiLineCheckedProblemPattern {
769 const candidate = value as INamedMultiLineCheckedProblemPattern;
770 return candidate && Types.isString(candidate.name) && Array.isArray(candidate.patterns) && MultiLineCheckedProblemPattern.is(candidate.patterns);
771 }
773 >
774 > export type NamedProblemPatterns = (Config.INamedProblemPattern | Config.INamedMultiLineCheckedProblemPattern)[];
775 >
776 > /**
777 > * A watching pattern
778 > */
779 > export interface IWatchingPattern {
780 > /**
781 > * The actual regular expression
782 > */
783 > regexp?: string;
784 >
785 > /**
786 > * The match group index of the filename. If provided the expression
787 > * is matched for that file only.
788 > */
789 > file?: number;
790 > }
791 >
792 > /**
793 > * A description to track the start and end of a watching task.
794 > */
795 > export interface IBackgroundMonitor {
796 >
797 > /**
798 > * If set to true the watcher starts in active mode. This is the
799 > * same as outputting a line that matches beginsPattern when the
800 > * task starts.
801 > */
802 > activeOnStart?: boolean;
803 >
804 > /**
805 > * If matched in the output the start of a watching task is signaled.
806 > */
807 > beginsPattern?: string | IWatchingPattern;
808 >
809 > /**
810 > * If matched in the output the end of a watching task is signaled.
811 > */
812 > endsPattern?: string | IWatchingPattern;
813 > }
814 >
815 > /**
816 > * A description of a problem matcher that detects problems
817 > * in build output.
818 > */
819 > export interface ProblemMatcher {
820 >
821 > /**
822 > * The name of a base problem matcher to use. If specified the
823 > * base problem matcher will be used as a template and properties
824 > * specified here will replace properties of the base problem
825 > * matcher
826 > */
827 > base?: string;
828 >
829 > /**
830 > * The owner of the produced VSCode problem. This is typically
831 > * the identifier of a VSCode language service if the problems are
832 > * to be merged with the one produced by the language service
833 > * or a generated internal id. Defaults to the generated internal id.
834 > */
835 > owner?: string;
836 >
837 > /**
838 > * A human-readable string describing the source of this problem.
839 > * E.g. 'typescript' or 'super lint'.
840 > */
841 > source?: string;
842 >
843 > /**
844 > * Specifies to which kind of documents the problems found by this
845 > * matcher are applied. Valid values are:
846 > *
847 > * "allDocuments": problems found in all documents are applied.
848 > * "openDocuments": problems found in documents that are open
849 > * are applied.
850 > * "closedDocuments": problems found in closed documents are
851 > * applied.
852 > */
853 > applyTo?: string;
854 >
855 > /**
856 > * The severity of the VSCode problem produced by this problem matcher.
857 > *
858 > * Valid values are:
859 > * "error": to produce errors.
860 > * "warning": to produce warnings.
861 > * "info": to produce infos.
862 > *
863 > * The value is used if a pattern doesn't specify a severity match group.
864 > * Defaults to "error" if omitted.
865 > */
866 > severity?: string;
867 >
868 > /**
869 > * Defines how filename reported in a problem pattern
870 > * should be read. Valid values are:
871 > * - "absolute": the filename is always treated absolute.
872 > * - "relative": the filename is always treated relative to
873 > * the current working directory. This is the default.
874 > * - ["relative", "path value"]: the filename is always
875 > * treated relative to the given path value.
876 > * - "autodetect": the filename is treated relative to
877 > * the current workspace directory, and if the file
878 > * does not exist, it is treated as absolute.
879 > * - ["autodetect", "path value"]: the filename is treated
880 > * relative to the given path value, and if it does not
881 > * exist, it is treated as absolute.
882 > * - ["search", { include?: "" | []; exclude?: "" | [] }]: The filename
883 > * needs to be searched under the directories named by the "include"
884 > * property and their nested subdirectories. With "exclude" property
885 > * present, the directories should be removed from the search. When
886 > * `include` is not unprovided, the current workspace directory should
887 > * be used as the default.
888 > */
889 > fileLocation?: Types.SingleOrMany<string> | ['search', SearchFileLocationArgs];
890 >
891 > /**
892 > * The name of a predefined problem pattern, the inline definition
893 > * of a problem pattern or an array of problem patterns to match
894 > * problems spread over multiple lines.
895 > */
896 > pattern?: string | Types.SingleOrMany<IProblemPattern>;
897 >
898 > /**
899 > * A regular expression signaling that a watched tasks begins executing
900 > * triggered through file watching.
901 > */
902 > watchedTaskBeginsRegExp?: string;
903 >
904 > /**
905 > * A regular expression signaling that a watched tasks ends executing.
906 > */
907 > watchedTaskEndsRegExp?: string;
908 >
909 > /**
910 > * @deprecated Use background instead.
911 > */
912 > watching?: IBackgroundMonitor;
913 > background?: IBackgroundMonitor;
914 > }
915 >
916 > export type SearchFileLocationArgs = {
917 > include?: Types.SingleOrMany<string>;
918 > exclude?: Types.SingleOrMany<string>;
919 > };
920 >
921 > export type ProblemMatcherType = string | ProblemMatcher | Array<string | ProblemMatcher>;
922 >
923 > export interface INamedProblemMatcher extends ProblemMatcher {
924 > /**
925 > * This name can be used to refer to the
926 > * problem matcher from within a task.
927 > */
928 > name: string;
929 >
930 > /**
931 > * A human readable label.
932 > */
933 > label?: string;
934 > }
935 >
936 > export function isNamedProblemMatcher(value: ProblemMatcher): value is INamedProblemMatcher {
937 return Types.isString((<INamedProblemMatcher>value).name);
938 }
940 >
941 > export class ProblemPatternParser extends Parser {
942 >
943 > constructor(logger: IProblemReporter) {
944 super(logger);
945 }
947 > public parse(value: Config.IProblemPattern): IProblemPattern;
948 > public parse(value: Config.MultiLineProblemPattern): MultiLineProblemPattern;
949 > public parse(value: Config.INamedProblemPattern): INamedProblemPattern;
950 > public parse(value: Config.INamedMultiLineCheckedProblemPattern): INamedMultiLineProblemPattern;
951 > public parse(value: Config.IProblemPattern | Config.MultiLineProblemPattern | Config.INamedProblemPattern | Config.INamedMultiLineCheckedProblemPattern): IProblemPattern | MultiLineProblemPattern | INamedProblemPattern | INamedMultiLineProblemPattern | null {
952 if (Config.NamedMultiLineCheckedProblemPattern.is(value)) {
953 return this.createNamedMultiLineProblemPattern(value);
965 }
966 }
968 > private createSingleProblemPattern(value: Config.ICheckedProblemPattern): IProblemPattern | null {
969 const result = this.doCreateSingleProblemPattern(value, true);
970 if (result === undefined) {
975 return this.validateProblemPattern([result]) ? result : null;
976 }
978 > private createNamedMultiLineProblemPattern(value: Config.INamedMultiLineCheckedProblemPattern): INamedMultiLineProblemPattern | null {
979 const validPatterns = this.createMultiLineProblemPattern(value.patterns);
980 if (!validPatterns) {
988 return result;
989 }
991 > private createMultiLineProblemPattern(values: Config.MultiLineCheckedProblemPattern): MultiLineProblemPattern | null {
992 const result: MultiLineProblemPattern = [];
993 for (let i = 0; i < values.length; i++) {
1013 return this.validateProblemPattern(result) ? result : null;
1014 }
1016 > private doCreateSingleProblemPattern(value: Config.ICheckedProblemPattern, setDefaults: boolean): IProblemPattern | undefined {
1017 const regexp = this.createRegularExpression(value.regexp);
1018 if (regexp === undefined) {
1061 return result;
1062 }
1064 > private validateProblemPattern(values: IProblemPattern[]): boolean {
1065 if (!values || values.length === 0) {
1066 this.error(localize('ProblemPatternParser.problemPattern.emptyPattern', 'The problem pattern is invalid. It must contain at least one pattern.'));
1089 return true;
1090 }
1092 > private createRegularExpression(value: string): RegExp | undefined {
1093 let result: RegExp | undefined;
1094 try {
1099 return result;
1100 }
1102 >
1103 > export class ExtensionRegistryReporter implements IProblemReporter {
1104 > constructor(private _collector: ExtensionMessageCollector, private _validationStatus: ValidationStatus = new ValidationStatus()) {
1105 }
1107 > public info(message: string): void {
1108 this._validationStatus.state = ValidationState.Info;
1109 this._collector.info(message);
1110 }
1112 > public warn(message: string): void {
1113 this._validationStatus.state = ValidationState.Warning;
1114 this._collector.warn(message);
1115 }
1117 > public error(message: string): void {
1118 this._validationStatus.state = ValidationState.Error;
1119 this._collector.error(message);
1120 }
1122 > public fatal(message: string): void {
1123 this._validationStatus.state = ValidationState.Fatal;
1124 this._collector.error(message);
1125 }
1127 > public get status(): ValidationStatus {
1128 return this._validationStatus;
1129 }
1131 >
1132 > export namespace Schemas {
1133 >
1134 > export const ProblemPattern: IJSONSchema = {
1135 > default: {
1136 > regexp: '^([^\\\\s].*)\\\\((\\\\d+,\\\\d+)\\\\):\\\\s*(.*)$',
1137 > file: 1,
1138 > location: 2,
1139 > message: 3
1140 > },
1141 > type: 'object',
1142 > additionalProperties: false,
1143 > properties: {
1144 > regexp: {
1145 > type: 'string',
1146 > description: localize('ProblemPatternSchema.regexp', 'The regular expression to find an error, warning or info in the output.')
1147 > },
1148 > kind: {
1149 > type: 'string',
1150 > description: localize('ProblemPatternSchema.kind', 'whether the pattern matches a location (file and line) or only a file.')
1151 > },
1152 > file: {
1153 > type: 'integer',
1154 > description: localize('ProblemPatternSchema.file', 'The match group index of the filename. If omitted 1 is used.')
1155 > },
1156 > location: {
1157 > type: 'integer',
1158 > description: localize('ProblemPatternSchema.location', 'The match group index of the problem\'s location. Valid location patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn). If omitted (line,column) is assumed.')
1159 > },
1160 > line: {
1161 > type: 'integer',
1162 > description: localize('ProblemPatternSchema.line', 'The match group index of the problem\'s line. Defaults to 2')
1163 > },
1164 > column: {
1165 > type: 'integer',
1166 > description: localize('ProblemPatternSchema.column', 'The match group index of the problem\'s line character. Defaults to 3')
1167 > },
1168 > endLine: {
1169 > type: 'integer',
1170 > description: localize('ProblemPatternSchema.endLine', 'The match group index of the problem\'s end line. Defaults to undefined')
1171 > },
1172 > endColumn: {
1173 > type: 'integer',
1174 > description: localize('ProblemPatternSchema.endColumn', 'The match group index of the problem\'s end line character. Defaults to undefined')
1175 > },
1176 > severity: {
1177 > type: 'integer',
1178 > description: localize('ProblemPatternSchema.severity', 'The match group index of the problem\'s severity. Defaults to undefined')
1179 > },
1180 > code: {
1181 > type: 'integer',
1182 > description: localize('ProblemPatternSchema.code', 'The match group index of the problem\'s code. Defaults to undefined')
1183 > },
1184 > message: {
1185 > type: 'integer',
1186 > description: localize('ProblemPatternSchema.message', 'The match group index of the message. If omitted it defaults to 4 if location is specified. Otherwise it defaults to 5.')
1187 > },
1188 > loop: {
1189 > type: 'boolean',
1190 > description: localize('ProblemPatternSchema.loop', 'In a multi line matcher loop indicated whether this pattern is executed in a loop as long as it matches. Can only specified on a last pattern in a multi line pattern.')
1191 > }
1192 > }
1193 > };
1194 >
1195 > export const NamedProblemPattern: IJSONSchema = Objects.deepClone(ProblemPattern);
1196 > NamedProblemPattern.properties = Objects.deepClone(NamedProblemPattern.properties) || {};
1197 > NamedProblemPattern.properties['name'] = {
1198 > type: 'string',
1199 > description: localize('NamedProblemPatternSchema.name', 'The name of the problem pattern.')
1200 > };
1201 >
1202 > export const MultiLineProblemPattern: IJSONSchema = {
1203 > type: 'array',
1204 > items: ProblemPattern
1205 > };
1206 >
1207 > export const NamedMultiLineProblemPattern: IJSONSchema = {
1208 > type: 'object',
1209 > additionalProperties: false,
1210 > properties: {
1211 > name: {
1212 > type: 'string',
1213 > description: localize('NamedMultiLineProblemPatternSchema.name', 'The name of the problem multi line problem pattern.')
1214 > },
1215 > patterns: {
1216 > type: 'array',
1217 > description: localize('NamedMultiLineProblemPatternSchema.patterns', 'The actual patterns.'),
1218 > items: ProblemPattern
1219 > }
1220 > }
1221 > };
1222 >
1223 > export const WatchingPattern: IJSONSchema = {
1224 > type: 'object',
1225 > additionalProperties: false,
1226 > properties: {
1227 > regexp: {
1228 > type: 'string',
1229 > description: localize('WatchingPatternSchema.regexp', 'The regular expression to detect the begin or end of a background task.')
1230 > },
1231 > file: {
1232 > type: 'integer',
1233 > description: localize('WatchingPatternSchema.file', 'The match group index of the filename. Can be omitted.')
1234 > },
1235 > }
1236 > };
1237 >
1238 > export const PatternType: IJSONSchema = {
1239 > anyOf: [
1240 > {
1241 > type: 'string',
1242 > description: localize('PatternTypeSchema.name', 'The name of a contributed or predefined pattern')
1243 > },
1244 > Schemas.ProblemPattern,
1245 > Schemas.MultiLineProblemPattern
1246 > ],
1247 > description: localize('PatternTypeSchema.description', 'A problem pattern or the name of a contributed or predefined problem pattern. Can be omitted if base is specified.')
1248 > };
1249 >
1250 > export const ProblemMatcher: IJSONSchema = {
1251 > type: 'object',
1252 > additionalProperties: false,
1253 > properties: {
1254 > base: {
1255 > type: 'string',
1256 > description: localize('ProblemMatcherSchema.base', 'The name of a base problem matcher to use.')
1257 > },
1258 > owner: {
1259 > type: 'string',
1260 > description: localize('ProblemMatcherSchema.owner', 'The owner of the problem inside Code. Can be omitted if base is specified. Defaults to \'external\' if omitted and base is not specified.')
1261 > },
1262 > source: {
1263 > type: 'string',
1264 > description: localize('ProblemMatcherSchema.source', 'A human-readable string describing the source of this diagnostic, e.g. \'typescript\' or \'super lint\'.')
1265 > },
1266 > severity: {
1267 > type: 'string',
1268 > enum: ['error', 'warning', 'info'],
1269 > description: localize('ProblemMatcherSchema.severity', 'The default severity for captures problems. Is used if the pattern doesn\'t define a match group for severity.')
1270 > },
1271 > applyTo: {
1272 > type: 'string',
1273 > enum: ['allDocuments', 'openDocuments', 'closedDocuments'],
1274 > description: localize('ProblemMatcherSchema.applyTo', 'Controls if a problem reported on a text document is applied only to open, closed or all documents.')
1275 > },
1276 > pattern: PatternType,
1277 > fileLocation: {
1278 > oneOf: [
1279 > {
1280 > type: 'string',
1281 > enum: ['absolute', 'relative', 'autoDetect', 'search']
1282 > },
1283 > {
1284 > type: 'array',
1285 > prefixItems: [
1286 > {
1287 > type: 'string',
1288 > enum: ['absolute', 'relative', 'autoDetect', 'search']
1289 > },
1290 > ],
1291 > minItems: 1,
1292 > maxItems: 1,
1293 > additionalItems: false
1294 > },
1295 > {
1296 > type: 'array',
1297 > prefixItems: [
1298 > { type: 'string', enum: ['relative', 'autoDetect'] },
1299 > { type: 'string' },
1300 > ],
1301 > minItems: 2,
1302 > maxItems: 2,
1303 > additionalItems: false,
1304 > examples: [
1305 > ['relative', '${workspaceFolder}'],
1306 > ['autoDetect', '${workspaceFolder}'],
1307 > ]
1308 > },
1309 > {
1310 > type: 'array',
1311 > prefixItems: [
1312 > { type: 'string', enum: ['search'] },
1313 > {
1314 > type: 'object',
1315 > properties: {
1316 > 'include': {
1317 > oneOf: [
1318 > { type: 'string' },
1319 > { type: 'array', items: { type: 'string' } }
1320 > ]
1321 > },
1322 > 'exclude': {
1323 > oneOf: [
1324 > { type: 'string' },
1325 > { type: 'array', items: { type: 'string' } }
1326 > ]
1327 > },
1328 > },
1329 > required: ['include']
1330 > }
1331 > ],
1332 > minItems: 2,
1333 > maxItems: 2,
1334 > additionalItems: false,
1335 > examples: [
1336 > ['search', { 'include': ['${workspaceFolder}'] }],
1337 > ['search', { 'include': ['${workspaceFolder}'], 'exclude': [] }]
1338 > ],
1339 > }
1340 > ],
1341 > description: localize('ProblemMatcherSchema.fileLocation', 'Defines how file names reported in a problem pattern should be interpreted. A relative fileLocation may be an array, where the second element of the array is the path of the relative file location. The search fileLocation mode, performs a deep (and, possibly, heavy) file system search within the directories specified by the include/exclude properties of the second element (or the current workspace directory if not specified).')
1342 > },
1343 > background: {
1344 > type: 'object',
1345 > additionalProperties: false,
1346 > description: localize('ProblemMatcherSchema.background', 'Patterns to track the begin and end of a matcher active on a background task.'),
1347 > properties: {
1348 > activeOnStart: {
1349 > type: 'boolean',
1350 > description: localize('ProblemMatcherSchema.background.activeOnStart', 'If set to true the background monitor starts in active mode. This is the same as outputting a line that matches beginsPattern when the task starts.')
1351 > },
1352 > beginsPattern: {
1353 > oneOf: [
1354 > {
1355 > type: 'string'
1356 > },
1357 > Schemas.WatchingPattern
1358 > ],
1359 > description: localize('ProblemMatcherSchema.background.beginsPattern', 'If matched in the output the start of a background task is signaled.')
1360 > },
1361 > endsPattern: {
1362 > oneOf: [
1363 > {
1364 > type: 'string'
1365 > },
1366 > Schemas.WatchingPattern
1367 > ],
1368 > description: localize('ProblemMatcherSchema.background.endsPattern', 'If matched in the output the end of a background task is signaled.')
1369 > }
1370 > }
1371 > },
1372 > watching: {
1373 > type: 'object',
1374 > additionalProperties: false,
1375 > deprecationMessage: localize('ProblemMatcherSchema.watching.deprecated', 'The watching property is deprecated. Use background instead.'),
1376 > description: localize('ProblemMatcherSchema.watching', 'Patterns to track the begin and end of a watching matcher.'),
1377 > properties: {
1378 > activeOnStart: {
1379 > type: 'boolean',
1380 > description: localize('ProblemMatcherSchema.watching.activeOnStart', 'If set to true the watcher starts in active mode. This is the same as outputting a line that matches beginsPattern when the task starts.')
1381 > },
1382 > beginsPattern: {
1383 > oneOf: [
1384 > {
1385 > type: 'string'
1386 > },
1387 > Schemas.WatchingPattern
1388 > ],
1389 > description: localize('ProblemMatcherSchema.watching.beginsPattern', 'If matched in the output the start of a watching task is signaled.')
1390 > },
1391 > endsPattern: {
1392 > oneOf: [
1393 > {
1394 > type: 'string'
1395 > },
1396 > Schemas.WatchingPattern
1397 > ],
1398 > description: localize('ProblemMatcherSchema.watching.endsPattern', 'If matched in the output the end of a watching task is signaled.')
1399 > }
1400 > }
1401 > }
1402 > }
1403 > };
1404 >
1405 > export const LegacyProblemMatcher: IJSONSchema = Objects.deepClone(ProblemMatcher);
1406 > LegacyProblemMatcher.properties = Objects.deepClone(LegacyProblemMatcher.properties) || {};
1407 > LegacyProblemMatcher.properties['watchedTaskBeginsRegExp'] = {
1408 > type: 'string',
1409 > deprecationMessage: localize('LegacyProblemMatcherSchema.watchedBegin.deprecated', 'This property is deprecated. Use the watching property instead.'),
1410 > description: localize('LegacyProblemMatcherSchema.watchedBegin', 'A regular expression signaling that a watched tasks begins executing triggered through file watching.')
1411 > };
1412 > LegacyProblemMatcher.properties['watchedTaskEndsRegExp'] = {
1413 > type: 'string',
1414 > deprecationMessage: localize('LegacyProblemMatcherSchema.watchedEnd.deprecated', 'This property is deprecated. Use the watching property instead.'),
1415 > description: localize('LegacyProblemMatcherSchema.watchedEnd', 'A regular expression signaling that a watched tasks ends executing.')
1416 > };
1417 >
1418 > export const NamedProblemMatcher: IJSONSchema = Objects.deepClone(ProblemMatcher);
1419 > NamedProblemMatcher.properties = Objects.deepClone(NamedProblemMatcher.properties) || {};
1420 > NamedProblemMatcher.properties.name = {
1421 > type: 'string',
1422 > description: localize('NamedProblemMatcherSchema.name', 'The name of the problem matcher used to refer to it.')
1423 > };
1424 > NamedProblemMatcher.properties.label = {
1425 > type: 'string',
1426 > description: localize('NamedProblemMatcherSchema.label', 'A human readable label of the problem matcher.')
1427 > };
1428 > }
1429 >
1430 > const problemPatternExtPoint = ExtensionsRegistry.registerExtensionPoint<Config.NamedProblemPatterns>({
1431 > extensionPoint: 'problemPatterns',
1432 > jsonSchema: {
1433 > description: localize('ProblemPatternExtPoint', 'Contributes problem patterns'),
1434 > type: 'array',
1435 > items: {
1436 > anyOf: [
1437 > Schemas.NamedProblemPattern,
1438 > Schemas.NamedMultiLineProblemPattern
1439 > ]
1440 > }
1441 > }
1442 > });
1443 >
1444 > export interface IProblemPatternRegistry {
1445 > onReady(): Promise<void>;
1446 >
1447 > get(key: string): IProblemPattern | MultiLineProblemPattern;
1448 > }
1449 >
1450 > class ProblemPatternRegistryImpl implements IProblemPatternRegistry {
1451 >
1452 > private patterns: IStringDictionary<Types.SingleOrMany<IProblemPattern>>;
1453 > private readyPromise: Promise<void>;
1454 >
1455 > constructor() {
1456 > this.patterns = Object.create(null);
1457 > this.fillDefaults();
1458 > this.readyPromise = new Promise<void>((resolve, reject) => {
1459 > problemPatternExtPoint.setHandler((extensions, delta) => {
1460 // We get all statically know extension during startup in one batch
1461 try {
1497 }
1498 resolve(undefined);
1499 > }); problemMatcher.ts
1500 > });
1501 > }
1502 >
1503 > public onReady(): Promise<void> {
1504 return this.readyPromise;
1505 }
1507 > public add(key: string, value: Types.SingleOrMany<IProblemPattern>): void {
1508 > this.patterns[key] = value;
1509 > }
1510 >
1511 > public get(key: string): Types.SingleOrMany<IProblemPattern> {
1512 > return this.patterns[key];
1513 > }
1514 >
1515 > private fillDefaults(): void {
1516 > this.add('msCompile', {
1517 > regexp: /^\s*(?:\s*\d+>)?(\S.*?)(?:\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\))?\s*:\s+(?:(\S+)\s+)?((?:fatal +)?error|warning|info)\s+(\w+\d+)?\s*:\s*(.*)$/,
1518 > kind: ProblemLocationKind.Location,
1519 > file: 1,
1520 > location: 2,
1521 > severity: 4,
1522 > code: 5,
1523 > message: 6
1524 > });
1525 > this.add('gulp-tsc', {
1526 > regexp: /^([^\s].*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(\d+)\s+(.*)$/,
1527 > kind: ProblemLocationKind.Location,
1528 > file: 1,
1529 > location: 2,
1530 > code: 3,
1531 > message: 4
1532 > });
1533 > this.add('cpp', {
1534 > regexp: /^(\S.*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(C\d+)\s*:\s*(.*)$/,
1535 > kind: ProblemLocationKind.Location,
1536 > file: 1,
1537 > location: 2,
1538 > severity: 3,
1539 > code: 4,
1540 > message: 5
1541 > });
1542 > this.add('csc', {
1543 > regexp: /^(\S.*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(CS\d+)\s*:\s*(.*)$/,
1544 > kind: ProblemLocationKind.Location,
1545 > file: 1,
1546 > location: 2,
1547 > severity: 3,
1548 > code: 4,
1549 > message: 5
1550 > });
1551 > this.add('vb', {
1552 > regexp: /^(\S.*)\((\d+|\d+,\d+|\d+,\d+,\d+,\d+)\):\s+(error|warning|info)\s+(BC\d+)\s*:\s*(.*)$/,
1553 > kind: ProblemLocationKind.Location,
1554 > file: 1,
1555 > location: 2,
1556 > severity: 3,
1557 > code: 4,
1558 > message: 5
1559 > });
1560 > this.add('lessCompile', {
1561 > regexp: /^\s*(.*) in file (.*) line no. (\d+)$/,
1562 > kind: ProblemLocationKind.Location,
1563 > message: 1,
1564 > file: 2,
1565 > line: 3
1566 > });
1567 > this.add('jshint', {
1568 > regexp: /^(.*):\s+line\s+(\d+),\s+col\s+(\d+),\s(.+?)(?:\s+\((\w)(\d+)\))?$/,
1569 > kind: ProblemLocationKind.Location,
1570 > file: 1,
1571 > line: 2,
1572 > character: 3,
1573 > message: 4,
1574 > severity: 5,
1575 > code: 6
1576 > });
1577 > this.add('jshint-stylish', [
1578 > {
1579 > regexp: /^(.+)$/,
1580 > kind: ProblemLocationKind.Location,
1581 > file: 1
1582 > },
1583 > {
1584 > regexp: /^\s+line\s+(\d+)\s+col\s+(\d+)\s+(.+?)(?:\s+\((\w)(\d+)\))?$/,
1585 > line: 1,
1586 > character: 2,
1587 > message: 3,
1588 > severity: 4,
1589 > code: 5,
1590 > loop: true
1591 > }
1592 > ]);
1593 > this.add('eslint-compact', {
1594 > regexp: /^(.+):\sline\s(\d+),\scol\s(\d+),\s(Error|Warning|Info)\s-\s(.+)\s\((.+)\)$/,
1595 > file: 1,
1596 > kind: ProblemLocationKind.Location,
1597 > line: 2,
1598 > character: 3,
1599 > severity: 4,
1600 > message: 5,
1601 > code: 6
1602 > });
1603 > this.add('eslint-stylish', [
1604 > {
1605 > regexp: /^((?:[a-zA-Z]:)*[./\\]+.*?)$/,
1606 > kind: ProblemLocationKind.Location,
1607 > file: 1
1608 > },
1609 > {
1610 > regexp: /^\s+(\d+):(\d+)\s+(error|warning|info)\s+(.+?)(?:\s\s+(.*))?$/,
1611 > line: 1,
1612 > character: 2,
1613 > severity: 3,
1614 > message: 4,
1615 > code: 5,
1616 > loop: true
1617 > }
1618 > ]);
1619 > this.add('go', {
1620 > regexp: /^([^:]*: )?((.:)?[^:]*):(\d+)(:(\d+))?: (.*)$/,
1621 > kind: ProblemLocationKind.Location,
1622 > file: 2,
1623 > line: 4,
1624 > character: 6,
1625 > message: 7
1626 > });
1627 > }
1628 > }
1629 >
1630 > export const ProblemPatternRegistry: IProblemPatternRegistry = new ProblemPatternRegistryImpl();
1631 >
1632 > export class ProblemMatcherParser extends Parser {
1633 >
1634 > constructor(logger: IProblemReporter) {
1635 super(logger);
1636 }
1638 > public parse(json: Config.ProblemMatcher): ProblemMatcher | undefined {
1639 const result = this.createProblemMatcher(json);
1640 if (!this.checkProblemMatcherValid(json, result)) {
1645 return result;
1646 }
1648 > private checkProblemMatcherValid(externalProblemMatcher: Config.ProblemMatcher, problemMatcher: ProblemMatcher | null): problemMatcher is ProblemMatcher {
1649 if (!problemMatcher) {
1650 this.error(localize('ProblemMatcherParser.noProblemMatcher', 'Error: the description can\'t be converted into a problem matcher:\n{0}\n', JSON.stringify(externalProblemMatcher, null, 4)));
1665 return true;
1666 }
1668 > private createProblemMatcher(description: Config.ProblemMatcher): ProblemMatcher | null {
1669 let result: ProblemMatcher | null = null;
1670
1769 return result;
1770 }
1772 > private createProblemPattern(value: string | Config.IProblemPattern | Config.MultiLineProblemPattern): Types.SingleOrMany<IProblemPattern> | null {
1773 if (Types.isString(value)) {
1774 const variableName: string = <string>value;
1796 return null;
1797 }
1799 > private addWatchingMatcher(external: Config.ProblemMatcher, internal: ProblemMatcher): void {
1800 const oldBegins = this.createRegularExpression(external.watchedTaskBeginsRegExp);
1801 const oldEnds = this.createRegularExpression(external.watchedTaskEndsRegExp);
1826 }
1827 }
1829 > private createWatchingPattern(external: string | Config.IWatchingPattern | undefined): IWatchingPattern | null {
1830 if (Types.isUndefinedOrNull(external)) {
1831 return null;
1846 return file ? { regexp, file } : { regexp, file: 1 };
1847 }
1849 > private createRegularExpression(value: string | undefined): RegExp | null {
1850 let result: RegExp | null = null;
1851 if (!value) {
1859 return result;
1860 }
1862 >
1863 > const problemMatchersExtPoint = ExtensionsRegistry.registerExtensionPoint<Config.INamedProblemMatcher[]>({
1864 > extensionPoint: 'problemMatchers',
1865 > deps: [problemPatternExtPoint],
1866 > jsonSchema: {
1867 > description: localize('ProblemMatcherExtPoint', 'Contributes problem matchers'),
1868 > type: 'array',
1869 > items: Schemas.NamedProblemMatcher
1870 > }
1871 > });
1872 >
1873 > export interface IProblemMatcherRegistry {
1874 > onReady(): Promise<void>;
1875 > get(name: string): INamedProblemMatcher;
1876 > keys(): string[];
1877 > readonly onMatcherChanged: Event<void>;
1878 > }
1879 >
1880 > class ProblemMatcherRegistryImpl implements IProblemMatcherRegistry {
1881 >
1882 > private matchers: IStringDictionary<INamedProblemMatcher>;
1883 > private readyPromise: Promise<void>;
1884 > private readonly _onMatchersChanged: Emitter<void> = new Emitter<void>();
1885 > public readonly onMatcherChanged: Event<void> = this._onMatchersChanged.event;
1886 >
1887 >
1888 > constructor() {
1889 > this.matchers = Object.create(null);
1890 > this.fillDefaults();
1891 > this.readyPromise = new Promise<void>((resolve, reject) => {
1892 > problemMatchersExtPoint.setHandler((extensions, delta) => {
1893 try {
1894 delta.removed.forEach(extension => {
1920 }
1921 resolve(undefined);
1922 > }); problemMatcher.ts
1923 > });
1924 > }
1925 >
1926 > public onReady(): Promise<void> {
1927 ProblemPatternRegistry.onReady();
1928 return this.readyPromise;
1929 }
1931 > public add(matcher: INamedProblemMatcher): void {
1932 > this.matchers[matcher.name] = matcher;
1933 > }
1934 >
1935 > public get(name: string): INamedProblemMatcher {
1936 return this.matchers[name];
1937 }
1939 > public keys(): string[] {
1940 return Object.keys(this.matchers);
1941 }
1943 > private fillDefaults(): void {
1944 > this.add({
1945 > name: 'msCompile',
1946 > label: localize('msCompile', 'Microsoft compiler problems'),
1947 > owner: 'msCompile',
1948 > source: 'cpp',
1949 > applyTo: ApplyToKind.allDocuments,
1950 > fileLocation: FileLocationKind.Absolute,
1951 > pattern: ProblemPatternRegistry.get('msCompile')
1952 > });
1953 >
1954 > this.add({
1955 > name: 'lessCompile',
1956 > label: localize('lessCompile', 'Less problems'),
1957 > deprecated: true,
1958 > owner: 'lessCompile',
1959 > source: 'less',
1960 > applyTo: ApplyToKind.allDocuments,
1961 > fileLocation: FileLocationKind.Absolute,
1962 > pattern: ProblemPatternRegistry.get('lessCompile'),
1963 > severity: Severity.Error
1964 > });
1965 >
1966 > this.add({
1967 > name: 'gulp-tsc',
1968 > label: localize('gulp-tsc', 'Gulp TSC Problems'),
1969 > owner: 'typescript',
1970 > source: 'ts',
1971 > applyTo: ApplyToKind.closedDocuments,
1972 > fileLocation: FileLocationKind.Relative,
1973 > filePrefix: '${workspaceFolder}',
1974 > pattern: ProblemPatternRegistry.get('gulp-tsc')
1975 > });
1976 >
1977 > this.add({
1978 > name: 'jshint',
1979 > label: localize('jshint', 'JSHint problems'),
1980 > owner: 'jshint',
1981 > source: 'jshint',
1982 > applyTo: ApplyToKind.allDocuments,
1983 > fileLocation: FileLocationKind.Absolute,
1984 > pattern: ProblemPatternRegistry.get('jshint')
1985 > });
1986 >
1987 > this.add({
1988 > name: 'jshint-stylish',
1989 > label: localize('jshint-stylish', 'JSHint stylish problems'),
1990 > owner: 'jshint',
1991 > source: 'jshint',
1992 > applyTo: ApplyToKind.allDocuments,
1993 > fileLocation: FileLocationKind.Absolute,
1994 > pattern: ProblemPatternRegistry.get('jshint-stylish')
1995 > });
1996 >
1997 > this.add({
1998 > name: 'eslint-compact',
1999 > label: localize('eslint-compact', 'ESLint compact problems'),
2000 > owner: 'eslint',
2001 > source: 'eslint',
2002 > applyTo: ApplyToKind.allDocuments,
2003 > fileLocation: FileLocationKind.Absolute,
2004 > filePrefix: '${workspaceFolder}',
2005 > pattern: ProblemPatternRegistry.get('eslint-compact')
2006 > });
2007 >
2008 > this.add({
2009 > name: 'eslint-stylish',
2010 > label: localize('eslint-stylish', 'ESLint stylish problems'),
2011 > owner: 'eslint',
2012 > source: 'eslint',
2013 > applyTo: ApplyToKind.allDocuments,
2014 > fileLocation: FileLocationKind.Absolute,
2015 > pattern: ProblemPatternRegistry.get('eslint-stylish')
2016 > });
2017 >
2018 > this.add({
2019 > name: 'go',
2020 > label: localize('go', 'Go problems'),
2021 > owner: 'go',
2022 > source: 'go',
2023 > applyTo: ApplyToKind.allDocuments,
2024 > fileLocation: FileLocationKind.Relative,
2025 > filePrefix: '${workspaceFolder}',
2026 > pattern: ProblemPatternRegistry.get('go')
2027 > });
2028 > }
2029 > }
2030 >
2031 > export const ProblemMatcherRegistry: IProblemMatcherRegistry = new ProblemMatcherRegistryImpl();
src/vs/base/common/parsers.ts 53 introduced LOC · 13 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- parsers.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > export const enum ValidationState {
7 > OK = 0,
8 > Info = 1,
9 > Warning = 2,
10 > Error = 3,
11 > Fatal = 4
12 > }
13 >
14 > export class ValidationStatus {
15 > private _state: ValidationState;
16 >
17 > constructor() {
18 this._state = ValidationState.OK;
19 }
20 > parsers.ts
21 > public get state(): ValidationState {
22 return this._state;
23 }
24 > parsers.ts
25 > public set state(value: ValidationState) {
26 if (value > this._state) {
27 this._state = value;
28 }
29 }
30 > parsers.ts
31 > public isOK(): boolean {
32 return this._state === ValidationState.OK;
33 }
34 > parsers.ts
35 > public isFatal(): boolean {
36 return this._state === ValidationState.Fatal;
37 }
38 > } parsers.ts
39 >
40 > export interface IProblemReporter {
41 > info(message: string): void;
42 > warn(message: string): void;
43 > error(message: string): void;
44 > fatal(message: string): void;
45 > status: ValidationStatus;
46 > }
47 >
48 > export abstract class Parser {
49 >
50 > private _problemReporter: IProblemReporter;
51 >
52 > constructor(problemReporter: IProblemReporter) {
53 this._problemReporter = problemReporter;
54 }
55 > parsers.ts
56 > public reset(): void {
57 this._problemReporter.status.state = ValidationState.OK;
58 }
59 > parsers.ts
60 > public get problemReporter(): IProblemReporter {
61 return this._problemReporter;
62 }
63 > parsers.ts
64 > public info(message: string): void {
65 this._problemReporter.info(message);
66 }
67 > parsers.ts
68 > public warn(message: string): void {
69 this._problemReporter.warn(message);
70 }
71 > parsers.ts
72 > public error(message: string): void {
73 this._problemReporter.error(message);
74 }
75 > parsers.ts
76 > public fatal(message: string): void {
77 this._problemReporter.fatal(message);
78 }
79 > } parsers.ts