Skip to content

Commit f12dbba

Browse files
authored
Merge branch 'master' into master
2 parents 3d4a9dd + dcae1fb commit f12dbba

27 files changed

+252
-94
lines changed

debugger-launchjson.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ The `symbolOptions` element allows customization of how the debugger searches fo
259259
"https://my-companies-symbols-server"
260260
],
261261
"searchMicrosoftSymbolServer": true,
262+
"searchNuGetOrgSymbolServer": true,
262263
"cachePath": "/symcache",
263264
"moduleFilter": {
264265
"mode": "loadAllButExcluded",
@@ -273,6 +274,8 @@ The `symbolOptions` element allows customization of how the debugger searches fo
273274

274275
**searchMicrosoftSymbolServer**: If `true` the Microsoft Symbol server (https://msdl.microsoft.com/download/symbols) is added to the symbols search path. If unspecified, this option defaults to `false`.
275276

277+
**searchNuGetOrgSymbolServer**: If `true` the Nuget.org Symbol server (https://symbols.nuget.org/download/symbols) is added to the symbols search path. If unspecified, this option defaults to `false`.
278+
276279
**cachePath**": Directory where symbols downloaded from symbol servers should be cached. If unspecified, on Windows the debugger will default to %TEMP%\\SymbolCache, and on Linux and macOS the debugger will default to ~/.dotnet/symbolcache.
277280

278281
**moduleFilter.mode**: This value is either `"loadAllButExcluded"` or `"loadOnlyIncluded"`. In `"loadAllButExcluded"` mode, the debugger loads symbols for all modules unless the module is in the 'excludedModules' array. In `"loadOnlyIncluded"` mode, the debugger will not attempt to load symbols for ANY module unless it is in the 'includedModules' array, or it is included through the 'includeSymbolsNextToModules' setting.

package.json

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3759,6 +3759,38 @@
37593759
{
37603760
"id": "xmlDocCommentText",
37613761
"description": ""
3762+
},
3763+
{
3764+
"id": "regexComment",
3765+
"description": ""
3766+
},
3767+
{
3768+
"id": "regexCharacterClass",
3769+
"description": ""
3770+
},
3771+
{
3772+
"id": "regexAnchor",
3773+
"description": ""
3774+
},
3775+
{
3776+
"id": "regexQuantifier",
3777+
"description": ""
3778+
},
3779+
{
3780+
"id": "regexGrouping",
3781+
"description": ""
3782+
},
3783+
{
3784+
"id": "regexAlternation",
3785+
"description": ""
3786+
},
3787+
{
3788+
"id": "regexSelfEscapedCharacter",
3789+
"description": ""
3790+
},
3791+
{
3792+
"id": "regexOtherEscape",
3793+
"description": ""
37623794
}
37633795
],
37643796
"semanticTokenModifiers": [],
@@ -3896,6 +3928,40 @@
38963928
],
38973929
"xmlDocCommentText": [
38983930
"comment.documentation.cs"
3931+
],
3932+
"regexComment": [
3933+
"string.regexp.comment.cs"
3934+
],
3935+
"regexCharacterClass": [
3936+
"constant.character.character-class.regexp.cs",
3937+
"constant.other.character-class.set.regexp.cs",
3938+
"constant.other.character-class.regexp.cs",
3939+
"constant.character.set.regexp.cs"
3940+
],
3941+
"regexAnchor": [
3942+
"keyword.control.anchor.regexp.cs"
3943+
],
3944+
"regexQuantifier": [
3945+
"keyword.operator.quantifier.regexp.cs"
3946+
],
3947+
"regexGrouping": [
3948+
"punctuation.definition.group.regexp.cs",
3949+
"punctuation.definition.group.assertion.regexp.cs",
3950+
"punctuation.definition.character-class.regexp.cs",
3951+
"punctuation.character.set.begin.regexp.cs",
3952+
"punctuation.character.set.end.regexp.cs",
3953+
"keyword.operator.negation.regexp.cs",
3954+
"support.other.parenthesis.regexp.cs"
3955+
],
3956+
"regexAlternation": [
3957+
"keyword.operator.or.regexp.cs",
3958+
"keyword.control.anchor.regexp.cs"
3959+
],
3960+
"regexSelfEscapedCharacter": [
3961+
"string.regexp.self-escaped-character.cs"
3962+
],
3963+
"regexOtherEscape": [
3964+
"string.regexp.other-escape.cs"
38993965
]
39003966
}
39013967
}

snippets/csharp.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,13 @@
253253
"body": ["namespace ${1:Name}", "{", "\t$0", "}"],
254254
"description": "Namespace"
255255
},
256+
"FileScopedNamespace": {
257+
"prefix": "fsnamespace",
258+
"body": [
259+
"namespace ${1:Name};"
260+
],
261+
"description": "File-scoped namespace"
262+
},
256263
"#if": {
257264
"prefix": "ifd",
258265
"body": ["#if ${1:true}", "\t ${TM_SELECTED_TEXT}$0", "#endif"],

src/assets.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,14 @@ export class AssetGenerator {
267267
private createWatchTaskDescription(): tasks.TaskDescription {
268268
let commandArgs = ['watch', 'run'];
269269

270-
this.AddAdditionalCommandArgs(commandArgs);
270+
const buildProject = this.getBuildProjectPath();
271+
if (buildProject) {
272+
commandArgs.push('--project');
273+
commandArgs.push(buildProject);
274+
}
275+
276+
// NOTE: Don't add any additional args, or this will disable hot reload. See:
277+
// https://github.com/dotnet/sdk/blob/957ae5ca599fdeaee425d23928d42da711373a5e/src/BuiltInTools/dotnet-watch/Program.cs#L247-L256
271278

272279
return {
273280
label: 'watch',
@@ -279,17 +286,26 @@ export class AssetGenerator {
279286
}
280287

281288
private AddAdditionalCommandArgs(commandArgs: string[]) {
289+
const buildProject = this.getBuildProjectPath();
290+
if (buildProject) {
291+
commandArgs.push(buildProject);
292+
}
293+
294+
commandArgs.push("/property:GenerateFullPaths=true");
295+
commandArgs.push("/consoleloggerparameters:NoSummary");
296+
}
297+
298+
private getBuildProjectPath() : string|null {
282299
let buildProject = this.startupProject;
283300
if (!buildProject) {
284301
buildProject = this.fallbackBuildProject;
285302
}
286303
if (buildProject) {
287304
const buildPath = path.join('${workspaceFolder}', path.relative(this.workspaceFolder.uri.fsPath, buildProject.Path));
288-
commandArgs.push(util.convertNativePathToPosix(buildPath));
305+
return util.convertNativePathToPosix(buildPath);
289306
}
290307

291-
commandArgs.push("/property:GenerateFullPaths=true");
292-
commandArgs.push("/consoleloggerparameters:NoSummary");
308+
return null;
293309
}
294310

295311
public createTasksConfiguration(): tasks.TaskConfiguration {

src/features/semanticTokensProvider.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,14 @@ enum CustomTokenType {
6464
xmlDocCommentName,
6565
xmlDocCommentProcessingInstruction,
6666
xmlDocCommentText,
67+
regexComment,
68+
regexCharacterClass,
69+
regexAnchor,
70+
regexQuantifier,
71+
regexGrouping,
72+
regexAlternation,
73+
regexSelfEscapedCharacter,
74+
regexOtherEscape,
6775
}
6876

6977
// The default TokenModifiers defined by VS Code https://github.com/microsoft/vscode/blob/master/src/vs/platform/theme/common/tokenClassificationRegistry.ts#L393
@@ -281,6 +289,14 @@ tokenTypes[CustomTokenType.xmlDocCommentEntityReference] = "xmlDocCommentEntityR
281289
tokenTypes[CustomTokenType.xmlDocCommentName] = "xmlDocCommentName";
282290
tokenTypes[CustomTokenType.xmlDocCommentProcessingInstruction] = "xmlDocCommentProcessingInstruction";
283291
tokenTypes[CustomTokenType.xmlDocCommentText] = "xmlDocCommentText";
292+
tokenTypes[CustomTokenType.regexComment] = "regexComment";
293+
tokenTypes[CustomTokenType.regexCharacterClass] = "regexCharacterClass";
294+
tokenTypes[CustomTokenType.regexAnchor] = "regexAnchor";
295+
tokenTypes[CustomTokenType.regexQuantifier] = "regexQuantifier";
296+
tokenTypes[CustomTokenType.regexGrouping] = "regexGrouping";
297+
tokenTypes[CustomTokenType.regexAlternation] = "regexAlternation";
298+
tokenTypes[CustomTokenType.regexSelfEscapedCharacter] = "regexSelfEscapedCharacter";
299+
tokenTypes[CustomTokenType.regexOtherEscape] = "regexOtherEscape";
284300

285301
const tokenModifiers: string[] = [];
286302
tokenModifiers[DefaultTokenModifier.declaration] = 'declaration';
@@ -348,15 +364,15 @@ tokenTypeMap[SemanticHighlightClassification.XmlLiteralEntityReference] = undefi
348364
tokenTypeMap[SemanticHighlightClassification.XmlLiteralName] = undefined;
349365
tokenTypeMap[SemanticHighlightClassification.XmlLiteralProcessingInstruction] = undefined;
350366
tokenTypeMap[SemanticHighlightClassification.XmlLiteralText] = undefined;
351-
tokenTypeMap[SemanticHighlightClassification.RegexComment] = DefaultTokenType.regexp;
352-
tokenTypeMap[SemanticHighlightClassification.RegexCharacterClass] = DefaultTokenType.regexp;
353-
tokenTypeMap[SemanticHighlightClassification.RegexAnchor] = DefaultTokenType.regexp;
354-
tokenTypeMap[SemanticHighlightClassification.RegexQuantifier] = DefaultTokenType.regexp;
355-
tokenTypeMap[SemanticHighlightClassification.RegexGrouping] = DefaultTokenType.regexp;
356-
tokenTypeMap[SemanticHighlightClassification.RegexAlternation] = DefaultTokenType.regexp;
367+
tokenTypeMap[SemanticHighlightClassification.RegexComment] = CustomTokenType.regexComment;
368+
tokenTypeMap[SemanticHighlightClassification.RegexCharacterClass] = CustomTokenType.regexCharacterClass;
369+
tokenTypeMap[SemanticHighlightClassification.RegexAnchor] = CustomTokenType.regexAnchor;
370+
tokenTypeMap[SemanticHighlightClassification.RegexQuantifier] = CustomTokenType.regexQuantifier;
371+
tokenTypeMap[SemanticHighlightClassification.RegexGrouping] = CustomTokenType.regexGrouping;
372+
tokenTypeMap[SemanticHighlightClassification.RegexAlternation] = CustomTokenType.regexAlternation;
357373
tokenTypeMap[SemanticHighlightClassification.RegexText] = DefaultTokenType.regexp;
358-
tokenTypeMap[SemanticHighlightClassification.RegexSelfEscapedCharacter] = DefaultTokenType.regexp;
359-
tokenTypeMap[SemanticHighlightClassification.RegexOtherEscape] = DefaultTokenType.regexp;
374+
tokenTypeMap[SemanticHighlightClassification.RegexSelfEscapedCharacter] = CustomTokenType.regexSelfEscapedCharacter;
375+
tokenTypeMap[SemanticHighlightClassification.RegexOtherEscape] = CustomTokenType.regexOtherEscape;
360376

361377
const tokenModifierMap: number[] = [];
362378
tokenModifierMap[SemanticHighlightModifier.Static] = 2 ** DefaultTokenModifier.static;

src/omnisharp/OmniSharpDotnetResolver.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,28 @@ export class OmniSharpDotnetResolver implements IHostExecutableResolver {
3434
throw new Error(`Unable to read dotnet version information. Error ${result.stderr}`);
3535
}
3636

37-
const segments = result.stdout.split('.').map(str => Number.parseInt(str));
38-
if (segments.length != 3) {
37+
const segments: number[] = [];
38+
const stdoutSplit = result.stdout.split('.');
39+
if (stdoutSplit.length != 3) {
3940
throw new Error(`Unknown result output from 'dotnet --version'. Received ${result.stdout}`);
4041
}
4142

43+
let isPrerelease = false;
44+
45+
for (let i = 0; i < 3; i++) {
46+
let segment = stdoutSplit[i];
47+
if (i === 2) {
48+
const dashIndex = segment.indexOf('-');
49+
if (dashIndex !== -1) {
50+
isPrerelease = true;
51+
segment = segment.substring(0, dashIndex);
52+
}
53+
}
54+
55+
segments.push(Number.parseInt(segment));
56+
}
57+
58+
4259
if (this.versionPartIsGreaterThanMinimum(segments[0], minimumDotnetMajor, result.stdout)
4360
|| this.versionPartIsGreaterThanMinimum(segments[1], minimumDotnetMinor, result.stdout)) {
4461
return {
@@ -48,7 +65,9 @@ export class OmniSharpDotnetResolver implements IHostExecutableResolver {
4865
};
4966
}
5067

51-
this.versionPartIsGreaterThanMinimum(segments[2], minimumDotnetPatch, result.stdout);
68+
// If the found SDK is a pre-release version of .NET, then we need to ensure that it's a _higher_ patch version than the required
69+
// minimum, not a prerelease version of the required minimum.
70+
this.versionPartIsGreaterThanMinimum(segments[2], minimumDotnetPatch, result.stdout, /*disallowExactMatch*/ isPrerelease);
5271

5372
return {
5473
version: result.stdout,
@@ -57,8 +76,8 @@ export class OmniSharpDotnetResolver implements IHostExecutableResolver {
5776
};
5877
}
5978

60-
private versionPartIsGreaterThanMinimum(actualVersion: number, minimumRequired: number, foundVersion: string): boolean {
61-
if (actualVersion < minimumRequired) {
79+
private versionPartIsGreaterThanMinimum(actualVersion: number, minimumRequired: number, foundVersion: string, disallowExactMatch: boolean = false): boolean {
80+
if (actualVersion < minimumRequired || (disallowExactMatch && actualVersion === minimumRequired)) {
6281
throw new Error(`Found dotnet version ${foundVersion}. Minimum required version is ${minimumDotnetMajor}.${minimumDotnetMinor}.${minimumDotnetPatch}.`);
6382
}
6483

src/omnisharp/launcher.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,15 +340,24 @@ function getConfigurationValue(globalConfig: vscode.WorkspaceConfiguration, csha
340340

341341
async function launchDotnet(launchInfo: LaunchInfo, cwd: string, args: string[], platformInfo: PlatformInformation, options: Options, dotnetResolver: IHostExecutableResolver): Promise<LaunchResult> {
342342
const dotnetInfo = await dotnetResolver.getHostExecutableInfo(options);
343-
const dotnet = platformInfo.isWindows() ? 'dotnet.exe' : 'dotnet';
343+
let command: string;
344344
const argsCopy = args.slice(0);
345-
argsCopy.unshift(launchInfo.DotnetLaunchPath);
346345

347-
const process = spawn(dotnet, argsCopy, { detached: false, cwd, env: dotnetInfo.env });
346+
347+
if (launchInfo.LaunchPath && !launchInfo.LaunchPath.endsWith('.dll')) {
348+
// If we're not being asked to launch a dll, assume whatever we're given is an executable
349+
command = launchInfo.LaunchPath;
350+
}
351+
else {
352+
command = platformInfo.isWindows() ? 'dotnet.exe' : 'dotnet';
353+
argsCopy.unshift(launchInfo.DotnetLaunchPath ?? launchInfo.LaunchPath);
354+
}
355+
356+
const process = spawn(command, argsCopy, { detached: false, cwd, env: dotnetInfo.env });
348357

349358
return {
350359
process,
351-
command: launchInfo.DotnetLaunchPath,
360+
command: launchInfo.DotnetLaunchPath ?? launchInfo.LaunchPath,
352361
hostVersion: dotnetInfo.version,
353362
hostPath: dotnetInfo.path,
354363
hostIsMono: false,

test/integrationTests/advisor.integration.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,21 @@ suite(`Advisor ${testAssetWorkspace.description}`, function () {
3131
this.skip();
3232
}
3333

34-
let activationResult = await activateCSharpExtension();
34+
const activation = await activateCSharpExtension();
3535
await testAssetWorkspace.restore();
3636

37-
if (!activationResult) {
37+
if (!activation) {
3838
throw new Error('Cannot activate extension.');
3939
} else {
40-
advisor = activationResult.advisor;
40+
advisor = activation.advisor;
4141
}
4242

4343
let fileName = 'completion.cs';
4444
let dir = testAssetWorkspace.projects[0].projectDirectoryPath;
4545
let fileUri = vscode.Uri.file(path.join(dir, fileName));
4646
await vscode.commands.executeCommand('vscode.open', fileUri);
47+
48+
await testAssetWorkspace.waitForIdle(activation.eventStream);
4749
});
4850

4951
suiteTeardown(async () => {

test/integrationTests/codeActionRename.integration.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ suite(`Code Action Rename ${testAssetWorkspace.description}`, function () {
2525
this.skip();
2626
}
2727

28-
await activateCSharpExtension();
29-
await testAssetWorkspace.restore();
28+
const activation = await activateCSharpExtension();
29+
await testAssetWorkspace.restoreAndWait(activation);
3030

3131
let fileName = 'A.cs';
3232
let projectDirectory = testAssetWorkspace.projects[0].projectDirectoryPath;

test/integrationTests/codeLensProvider.integration.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ suite(`CodeLensProvider: ${testAssetWorkspace.description}`, function () {
2323
}
2424

2525
should();
26-
await activateCSharpExtension();
26+
const activation = await activateCSharpExtension();
2727
await testAssetWorkspace.restore();
2828

2929
let fileName = 'Program.cs';
@@ -36,6 +36,8 @@ suite(`CodeLensProvider: ${testAssetWorkspace.description}`, function () {
3636
await csharpConfig.update('testsCodeLens.enabled', true);
3737

3838
await vscode.commands.executeCommand("vscode.open", fileUri);
39+
40+
await testAssetWorkspace.waitForIdle(activation.eventStream);
3941
});
4042

4143
suiteTeardown(async () => {
@@ -75,8 +77,8 @@ suite(`CodeLensProvider options: ${testAssetWorkspace.description}`, function ()
7577
this.skip();
7678
}
7779
else {
78-
await activateCSharpExtension();
79-
await testAssetWorkspace.restore();
80+
const activation = await activateCSharpExtension();
81+
await testAssetWorkspace.restoreAndWait(activation);
8082

8183
let fileName = 'UnitTest1.cs';
8284
let projectDirectory = testAssetWorkspace.projects[2].projectDirectoryPath;

0 commit comments

Comments
 (0)