Skip to content

Commit f86e056

Browse files
committed
Merge branch 'main' into joh/bulkEditSave
2 parents 22c5f41 + 8864c16 commit f86e056

File tree

170 files changed

+3672
-2315
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

170 files changed

+3672
-2315
lines changed

build/gulpfile.reh.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,13 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa
311311
);
312312
} else if (platform === 'linux' || platform === 'alpine' || platform === 'darwin') {
313313
result = es.merge(result,
314-
gulp.src('resources/server/bin/remote-cli/code.sh', { base: '.' })
314+
gulp.src(`resources/server/bin/remote-cli/${platform === 'darwin' ? 'code-darwin.sh' : 'code-linux.sh'}`, { base: '.' })
315315
.pipe(replace('@@VERSION@@', version))
316316
.pipe(replace('@@COMMIT@@', commit))
317317
.pipe(replace('@@APPNAME@@', product.applicationName))
318318
.pipe(rename(`bin/remote-cli/${product.applicationName}`))
319319
.pipe(util.setExecutableBit()),
320-
gulp.src('resources/server/bin/helpers/browser.sh', { base: '.' })
320+
gulp.src(`resources/server/bin/helpers/${platform === 'darwin' ? 'browser-darwin.sh' : 'browser-linux.sh'}`, { base: '.' })
321321
.pipe(replace('@@VERSION@@', version))
322322
.pipe(replace('@@COMMIT@@', commit))
323323
.pipe(replace('@@APPNAME@@', product.applicationName))

extensions/markdown-language-features/src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function registerMarkdownLanguageFeatures(
6767
vscode.languages.registerFoldingRangeProvider(selector, new MdFoldingProvider(engine)),
6868
vscode.languages.registerSelectionRangeProvider(selector, new MdSmartSelect(engine)),
6969
vscode.languages.registerWorkspaceSymbolProvider(new MdWorkspaceSymbolProvider(symbolProvider, workspaceContents)),
70-
vscode.languages.registerReferenceProvider(selector, new MdReferencesProvider(linkProvider, workspaceContents, engine)),
70+
vscode.languages.registerReferenceProvider(selector, new MdReferencesProvider(linkProvider, workspaceContents, engine, githubSlugifier)),
7171
MdPathCompletionProvider.register(selector, engine, linkProvider),
7272
);
7373
}

extensions/markdown-language-features/src/languageFeatures/documentLinkProvider.ts

Lines changed: 114 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as nls from 'vscode-nls';
88
import * as uri from 'vscode-uri';
99
import { OpenDocumentLinkCommand } from '../commands/openDocumentLink';
1010
import { MarkdownEngine } from '../markdownEngine';
11+
import { coalesce } from '../util/arrays';
1112
import { getUriForLinkWithKnownExternalScheme, isOfScheme, Schemes } from '../util/schemes';
1213
import { SkinnyTextDocument } from '../workspaceContents';
1314

@@ -20,19 +21,28 @@ export interface ExternalLinkTarget {
2021

2122
export interface InternalLinkTarget {
2223
readonly kind: 'internal';
23-
24-
readonly fromResource: vscode.Uri;
2524
readonly path: vscode.Uri;
2625
readonly fragment: string;
2726
}
2827

29-
export type LinkTarget = ExternalLinkTarget | InternalLinkTarget;
28+
export interface ReferenceLinkTarget {
29+
readonly kind: 'reference';
30+
readonly ref: string;
31+
}
32+
33+
export interface DefinitionLinkTarget {
34+
readonly kind: 'definition';
35+
readonly ref: string;
36+
readonly target: ExternalLinkTarget | InternalLinkTarget;
37+
}
38+
39+
export type LinkTarget = ExternalLinkTarget | InternalLinkTarget | ReferenceLinkTarget | DefinitionLinkTarget;
3040

3141

3242
function parseLink(
3343
document: SkinnyTextDocument,
3444
link: string,
35-
): LinkTarget | undefined {
45+
): ExternalLinkTarget | InternalLinkTarget | undefined {
3646
const cleanLink = stripAngleBrackets(link);
3747
const externalSchemeUri = getUriForLinkWithKnownExternalScheme(cleanLink);
3848
if (externalSchemeUri) {
@@ -75,7 +85,6 @@ function parseLink(
7585

7686
return {
7787
kind: 'internal',
78-
fromResource: document.uri,
7988
path: resourceUri,
8089
fragment: tempUri.fragment,
8190
};
@@ -88,6 +97,7 @@ function getWorkspaceFolder(document: SkinnyTextDocument) {
8897

8998
export interface LinkData {
9099
readonly target: LinkTarget;
100+
readonly sourceResource: vscode.Uri;
91101
readonly sourceRange: vscode.Range;
92102
}
93103

@@ -107,6 +117,7 @@ function extractDocumentLink(
107117
}
108118
return {
109119
target: linkTarget,
120+
sourceResource: document.uri,
110121
sourceRange: new vscode.Range(linkStart, linkEnd)
111122
};
112123
} catch {
@@ -172,36 +183,63 @@ function isLinkInsideCode(code: CodeInDocument, link: LinkData) {
172183
code.inline.some(position => position.intersection(link.sourceRange));
173184
}
174185

175-
function createDocumentLink(sourceRange: vscode.Range, target: LinkTarget) {
176-
if (target.kind === 'external') {
177-
return new vscode.DocumentLink(sourceRange, target.uri);
178-
} else {
179-
180-
const uri = OpenDocumentLinkCommand.createCommandUri(target.fromResource, target.path, target.fragment);
181-
const documentLink = new vscode.DocumentLink(sourceRange, uri);
182-
documentLink.tooltip = localize('documentLink.tooltip', 'Follow link');
183-
return documentLink;
184-
}
185-
}
186-
187186
export class MdLinkProvider implements vscode.DocumentLinkProvider {
187+
188188
constructor(
189189
private readonly engine: MarkdownEngine
190190
) { }
191191

192192
public async provideDocumentLinks(
193193
document: SkinnyTextDocument,
194-
_token: vscode.CancellationToken
194+
token: vscode.CancellationToken
195195
): Promise<vscode.DocumentLink[]> {
196-
const text = document.getText();
197-
const inlineLinks = await this.getInlineLinks(text, document);
198-
return [
199-
...inlineLinks.map(data => createDocumentLink(data.sourceRange, data.target)),
200-
...this.getReferenceLinks(text, document)
201-
];
196+
const allLinks = await this.getAllLinks(document);
197+
if (token.isCancellationRequested) {
198+
return [];
199+
}
200+
201+
const definitionSet = new LinkDefinitionSet(allLinks);
202+
return coalesce(allLinks
203+
.map(data => this.toValidDocumentLink(data, definitionSet)));
204+
}
205+
206+
private toValidDocumentLink(link: LinkData, definitionSet: LinkDefinitionSet): vscode.DocumentLink | undefined {
207+
switch (link.target.kind) {
208+
case 'external': {
209+
return new vscode.DocumentLink(link.sourceRange, link.target.uri);
210+
}
211+
case 'internal': {
212+
const uri = OpenDocumentLinkCommand.createCommandUri(link.sourceResource, link.target.path, link.target.fragment);
213+
const documentLink = new vscode.DocumentLink(link.sourceRange, uri);
214+
documentLink.tooltip = localize('documentLink.tooltip', 'Follow link');
215+
return documentLink;
216+
}
217+
case 'reference': {
218+
const def = definitionSet.lookup(link.target.ref);
219+
if (def) {
220+
return new vscode.DocumentLink(
221+
link.sourceRange,
222+
vscode.Uri.parse(`command:_markdown.moveCursorToPosition?${encodeURIComponent(JSON.stringify([def.sourceRange.start.line, def.sourceRange.start.character]))}`));
223+
} else {
224+
return undefined;
225+
}
226+
}
227+
case 'definition':
228+
return this.toValidDocumentLink({ sourceRange: link.sourceRange, sourceResource: link.sourceResource, target: link.target.target }, definitionSet);
229+
}
230+
}
231+
232+
public async getAllLinks(document: SkinnyTextDocument): Promise<LinkData[]> {
233+
return Array.from([
234+
...(await this.getInlineLinks(document)),
235+
...this.getReferenceLinks(document),
236+
...this.getDefinitionLinks(document),
237+
]);
202238
}
203239

204-
public async getInlineLinks(text: string, document: SkinnyTextDocument): Promise<LinkData[]> {
240+
private async getInlineLinks(document: SkinnyTextDocument): Promise<LinkData[]> {
241+
const text = document.getText();
242+
205243
const results: LinkData[] = [];
206244
const codeInDocument = await findCode(document, this.engine);
207245
for (const match of text.matchAll(linkPattern)) {
@@ -217,8 +255,8 @@ export class MdLinkProvider implements vscode.DocumentLinkProvider {
217255
return results;
218256
}
219257

220-
public *getReferenceLinks(text: string, document: SkinnyTextDocument): Iterable<vscode.DocumentLink> {
221-
const definitions = this.getDefinitions(text, document);
258+
private *getReferenceLinks(document: SkinnyTextDocument): Iterable<LinkData> {
259+
const text = document.getText();
222260
for (const match of text.matchAll(referenceLinkPattern)) {
223261
let linkStart: vscode.Position;
224262
let linkEnd: vscode.Position;
@@ -237,32 +275,19 @@ export class MdLinkProvider implements vscode.DocumentLinkProvider {
237275
continue;
238276
}
239277

240-
try {
241-
const link = definitions.get(reference);
242-
if (link) {
243-
yield new vscode.DocumentLink(
244-
new vscode.Range(linkStart, linkEnd),
245-
vscode.Uri.parse(`command:_markdown.moveCursorToPosition?${encodeURIComponent(JSON.stringify([link.linkRange.start.line, link.linkRange.start.character]))}`));
278+
yield {
279+
sourceRange: new vscode.Range(linkStart, linkEnd),
280+
sourceResource: document.uri,
281+
target: {
282+
kind: 'reference',
283+
ref: reference,
246284
}
247-
} catch (e) {
248-
// noop
249-
}
250-
}
251-
252-
for (const definition of definitions.values()) {
253-
try {
254-
const target = parseLink(document, definition.link);
255-
if (target) {
256-
yield createDocumentLink(definition.linkRange, target);
257-
}
258-
} catch (e) {
259-
// noop
260-
}
285+
};
261286
}
262287
}
263288

264-
public getDefinitions(text: string, document: SkinnyTextDocument): Map<string, { readonly link: string; readonly linkRange: vscode.Range }> {
265-
const out = new Map<string, { link: string; linkRange: vscode.Range }>();
289+
public *getDefinitionLinks(document: SkinnyTextDocument): Iterable<LinkData> {
290+
const text = document.getText();
266291
for (const match of text.matchAll(definitionPattern)) {
267292
const pre = match[1];
268293
const reference = match[2];
@@ -272,19 +297,50 @@ export class MdLinkProvider implements vscode.DocumentLinkProvider {
272297
if (angleBracketLinkRe.test(link)) {
273298
const linkStart = document.positionAt(offset + 1);
274299
const linkEnd = document.positionAt(offset + link.length - 1);
275-
out.set(reference, {
276-
link: link.substring(1, link.length - 1),
277-
linkRange: new vscode.Range(linkStart, linkEnd)
278-
});
300+
const target = parseLink(document, link.substring(1, link.length - 1));
301+
if (target) {
302+
yield {
303+
sourceResource: document.uri,
304+
sourceRange: new vscode.Range(linkStart, linkEnd),
305+
target: {
306+
kind: 'definition',
307+
ref: reference,
308+
target
309+
}
310+
};
311+
}
279312
} else {
280313
const linkStart = document.positionAt(offset);
281314
const linkEnd = document.positionAt(offset + link.length);
282-
out.set(reference, {
283-
link: link,
284-
linkRange: new vscode.Range(linkStart, linkEnd)
285-
});
315+
const target = parseLink(document, link);
316+
if (target) {
317+
yield {
318+
sourceResource: document.uri,
319+
sourceRange: new vscode.Range(linkStart, linkEnd),
320+
target: {
321+
kind: 'definition',
322+
ref: reference,
323+
target,
324+
}
325+
};
326+
}
286327
}
287328
}
288-
return out;
329+
}
330+
}
331+
332+
export class LinkDefinitionSet {
333+
private readonly _map = new Map<string, LinkData>();
334+
335+
constructor(links: Iterable<LinkData>) {
336+
for (const link of links) {
337+
if (link.target.kind === 'definition') {
338+
this._map.set(link.target.ref, link);
339+
}
340+
}
341+
}
342+
343+
public lookup(ref: string): LinkData | undefined {
344+
return this._map.get(ref);
289345
}
290346
}

extensions/markdown-language-features/src/languageFeatures/pathCompletions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { MarkdownEngine } from '../markdownEngine';
99
import { TableOfContents } from '../tableOfContents';
1010
import { resolveUriToMarkdownFile } from '../util/openDocumentLink';
1111
import { SkinnyTextDocument } from '../workspaceContents';
12-
import { MdLinkProvider } from './documentLinkProvider';
12+
import { DefinitionLinkTarget, MdLinkProvider } from './documentLinkProvider';
1313

1414
enum CompletionContextKind {
1515
/** `[...](|)` */
@@ -236,11 +236,11 @@ export class MdPathCompletionProvider implements vscode.CompletionItemProvider {
236236
const insertionRange = new vscode.Range(context.linkTextStartPosition, position);
237237
const replacementRange = new vscode.Range(insertionRange.start, position.translate({ characterDelta: context.linkSuffix.length }));
238238

239-
const definitions = this.linkProvider.getDefinitions(document.getText(), document);
239+
const definitions = this.linkProvider.getDefinitionLinks(document);
240240
for (const def of definitions) {
241241
yield {
242242
kind: vscode.CompletionItemKind.Reference,
243-
label: def[0],
243+
label: (def.target as DefinitionLinkTarget).ref,
244244
range: {
245245
inserting: insertionRange,
246246
replacing: replacementRange,

0 commit comments

Comments
 (0)