Skip to content

Commit 4916b2f

Browse files
authored
Prevent looping between C and C++. (#10309)
* Prevent looping between C and C++.
1 parent 54c73ea commit 4916b2f

File tree

4 files changed

+46
-27
lines changed

4 files changed

+46
-27
lines changed

Extension/src/LanguageServer/client.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { SourceFileConfigurationItem, WorkspaceBrowseConfiguration, SourceFileCo
2727
import { Status, IntelliSenseStatus } from 'vscode-cpptools/out/testApi';
2828
import { getLocaleId, getLocalizedString, LocalizeStringParams } from './localization';
2929
import { Location, TextEdit } from './commonTypes';
30-
import { makeVscodeRange, makeVscodeLocation } from './utils';
30+
import { makeVscodeRange, makeVscodeLocation, handleChangedFromCppToC } from './utils';
3131
import * as util from '../common';
3232
import * as configs from './configurations';
3333
import { CppSettings, getEditorConfigSettings, OtherSettings, SettingsParams, WorkspaceFolderSettingsParams } from './settings';
@@ -1933,6 +1933,9 @@ export class DefaultClient implements Client {
19331933
const languageId: string = params.isC ? "c" : (params.isCuda ? "cuda-cpp" : "cpp");
19341934
const document: vscode.TextDocument = await vscode.workspace.openTextDocument(params.path);
19351935
if (!!document && document.languageId !== languageId) {
1936+
if (document.languageId === "cpp" && languageId === "c") {
1937+
handleChangedFromCppToC(document);
1938+
}
19361939
vscode.languages.setTextDocumentLanguage(document, languageId);
19371940
}
19381941
}

Extension/src/LanguageServer/extension.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { UI, getUI } from './ui';
1515
import { Client, DefaultClient, DoxygenCodeActionCommandArguments, openFileVersions } from './client';
1616
import { CodeAnalysisDiagnosticIdentifiersAndUri, CodeActionDiagnosticInfo, codeAnalysisCodeToFixes,
1717
codeAnalysisFileToCodeActions, codeAnalysisAllFixes } from './codeAnalysis';
18-
import { makeCpptoolsRange, rangeEquals } from './utils';
18+
import { makeCpptoolsRange, rangeEquals, shouldChangeFromCToCpp } from './utils';
1919
import { ClientCollection } from './clientCollection';
2020
import { CppSettings } from './settings';
2121
import { PersistentState } from './persistentState';
@@ -342,18 +342,15 @@ export function processDelayedDidOpen(document: vscode.TextDocument): boolean {
342342
};
343343
let languageChanged: boolean = false;
344344
// Work around vscode treating ".C" or ".H" as c, by adding this file name to file associations as cpp
345-
if ((document.uri.path.endsWith(".C") || document.uri.path.endsWith(".H")) && document.languageId === "c") {
346-
const cppSettings: CppSettings = new CppSettings();
347-
if (cppSettings.autoAddFileAssociations) {
348-
const fileName: string = path.basename(document.uri.fsPath);
349-
const mappingString: string = fileName + "@" + document.uri.fsPath;
350-
client.addFileAssociations(mappingString, "cpp");
351-
client.sendDidChangeSettings();
352-
vscode.languages.setTextDocumentLanguage(document, "cpp").then((newDoc: vscode.TextDocument) => {
353-
finishDidOpen(newDoc);
354-
});
355-
languageChanged = true;
356-
}
345+
if (document.languageId === "c" && shouldChangeFromCToCpp(document)) {
346+
const baseFileName: string = path.basename(document.fileName);
347+
const mappingString: string = baseFileName + "@" + document.fileName;
348+
client.addFileAssociations(mappingString, "cpp");
349+
client.sendDidChangeSettings();
350+
vscode.languages.setTextDocumentLanguage(document, "cpp").then((newDoc: vscode.TextDocument) => {
351+
finishDidOpen(newDoc);
352+
});
353+
languageChanged = true;
357354
}
358355
if (!languageChanged) {
359356
finishDidOpen(document);

Extension/src/LanguageServer/protocolFilter.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import * as path from 'path';
88
import { Middleware } from 'vscode-languageclient';
99
import { Client } from './client';
1010
import * as vscode from 'vscode';
11-
import { CppSettings } from './settings';
1211
import { clients, onDidChangeActiveTextEditor } from './extension';
12+
import { shouldChangeFromCToCpp } from './utils';
1313

1414
export function createProtocolFilter(): Middleware {
1515
// Disabling lint for invoke handlers
@@ -43,18 +43,15 @@ export function createProtocolFilter(): Middleware {
4343
}
4444
};
4545
let languageChanged: boolean = false;
46-
if ((document.uri.path.endsWith(".C") || document.uri.path.endsWith(".H")) && document.languageId === "c") {
47-
const cppSettings: CppSettings = new CppSettings();
48-
if (cppSettings.autoAddFileAssociations) {
49-
const fileName: string = path.basename(document.uri.fsPath);
50-
const mappingString: string = fileName + "@" + document.uri.fsPath;
51-
me.addFileAssociations(mappingString, "cpp");
52-
me.sendDidChangeSettings();
53-
vscode.languages.setTextDocumentLanguage(document, "cpp").then((newDoc: vscode.TextDocument) => {
54-
finishDidOpen(newDoc);
55-
});
56-
languageChanged = true;
57-
}
46+
if (document.languageId === "c" && shouldChangeFromCToCpp(document)) {
47+
const baesFileName: string = path.basename(document.fileName);
48+
const mappingString: string = baesFileName + "@" + document.fileName;
49+
me.addFileAssociations(mappingString, "cpp");
50+
me.sendDidChangeSettings();
51+
vscode.languages.setTextDocumentLanguage(document, "cpp").then((newDoc: vscode.TextDocument) => {
52+
finishDidOpen(newDoc);
53+
});
54+
languageChanged = true;
5855
}
5956
if (!languageChanged) {
6057
finishDidOpen(document);

Extension/src/LanguageServer/utils.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import * as vscode from 'vscode';
77
import { Range } from 'vscode-languageclient';
88
import { Location, TextEdit } from './commonTypes';
9+
import { CppSettings } from './settings';
910

1011
export function makeCpptoolsRange(vscRange: vscode.Range): Range {
1112
return { start: { line: vscRange.start.line, character: vscRange.start.character },
@@ -28,3 +29,24 @@ export function rangeEquals(range1: vscode.Range | Range, range2: vscode.Range |
2829
return range1.start.line === range2.start.line && range1.start.character === range2.start.character &&
2930
range1.end.line === range2.end.line && range1.end.character === range2.end.character;
3031
}
32+
33+
// Check this before attempting to switch a document from C to C++.
34+
export function shouldChangeFromCToCpp(document: vscode.TextDocument): boolean {
35+
if ((document.fileName.endsWith(".C") || document.fileName.endsWith(".H"))) {
36+
const cppSettings: CppSettings = new CppSettings();
37+
if (cppSettings.autoAddFileAssociations) {
38+
return !docsChangedFromCppToC.has(document.fileName);
39+
}
40+
// We could potentially add a new setting to enable switching to cpp even when files.associations isn't changed.
41+
}
42+
return false;
43+
}
44+
45+
// Call this before changing from C++ to C.
46+
export function handleChangedFromCppToC(document: vscode.TextDocument): void {
47+
if (shouldChangeFromCToCpp(document)) {
48+
docsChangedFromCppToC.add(document.fileName);
49+
}
50+
}
51+
52+
const docsChangedFromCppToC: Set<string> = new Set<string>();

0 commit comments

Comments
 (0)