Move to "Auto Detect" in language picker and use smarts in Auto Detect for non-Untitled files

上级 05654069
......@@ -1121,10 +1121,6 @@ export class ShowLanguageExtensionsAction extends Action {
}
}
interface IDetectedLanguageQuickPickItem extends IQuickPickItem {
guessRank: number;
}
export class ChangeModeAction extends Action {
static readonly ID = 'workbench.action.editor.changeLanguageMode';
......@@ -1165,21 +1161,14 @@ export class ChangeModeAction extends Action {
}
let hasLanguageSupport = !!resource;
let detectedLanguages: string[] = [];
if (resource?.scheme === Schemas.untitled && !this.textFileService.untitled.get(resource)?.hasAssociatedFilePath) {
hasLanguageSupport = false; // no configuration for untitled resources (e.g. "Untitled-1")
// Detect languages since we are in an untitled file
detectedLanguages = await this.languageDetectionService.detectLanguages(resource);
}
// All languages are valid picks
const languages = this.modeService.getRegisteredLanguageNames();
const picks: QuickPickInput[] = languages.sort()
.filter(lang => {
const modeId = this.modeService.getModeIdForLanguageName(lang.toLowerCase()) || 'unknown';
return (detectedLanguages.indexOf(modeId) === -1);
}).map(lang => {
.map(lang => {
const modeId = this.modeService.getModeIdForLanguageName(lang.toLowerCase()) || 'unknown';
const extensions = this.modeService.getExtensions(lang).join(' ');
let description: string;
......@@ -1221,32 +1210,7 @@ export class ChangeModeAction extends Action {
const autoDetectMode: IQuickPickItem = {
label: localize('autoDetect', "Auto Detect")
};
if (hasLanguageSupport) {
picks.unshift(autoDetectMode);
} else if (detectedLanguages) {
// Add untitled detected languages
let index = detectedLanguages.length - 1;
for (const modeId of detectedLanguages.reverse()) {
const lang = this.modeService.getLanguageName(modeId) || 'unknown';
let description: string;
if (currentLanguageId === lang) {
description = localize('languageDescriptionCurrent', "({0}) - Current Language", modeId);
} else {
description = localize('languageDescriptionConfigured', "({0})", modeId);
}
const pick: IDetectedLanguageQuickPickItem = {
label: lang,
iconClasses: getIconClassesForModeId(modeId),
description,
guessRank: index--,
};
picks.unshift(pick);
}
picks.unshift({ type: 'separator', label: localize('detectedLanguagesPicks', "detected languages (identifier)") });
}
picks.unshift(autoDetectMode);
const pick = await this.quickInputService.pick(picks, { placeHolder: localize('pickLanguage', "Select Language Mode"), matchOnDescription: true });
if (!pick) {
......@@ -1280,27 +1244,39 @@ export class ChangeModeAction extends Action {
// Find mode
let languageSelection: ILanguageSelection | undefined;
let detectedLanguage: string | undefined;
if (pick === autoDetectMode) {
if (textModel) {
const resource = EditorResourceAccessor.getOriginalUri(activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY });
if (resource) {
languageSelection = this.modeService.createByFilepathOrFirstLine(resource, textModel.getLineContent(1));
// Detect languages since we are in an untitled file
let modeId: string | undefined = withNullAsUndefined(this.modeService.getModeIdByFilepathOrFirstLine(resource, textModel.getLineContent(1)));
if (!modeId) {
detectedLanguage = await this.languageDetectionService.detectLanguage(resource);
modeId = detectedLanguage;
}
if (modeId) {
languageSelection = this.modeService.create(modeId);
}
}
}
} else {
languageSelection = this.modeService.createByLanguageName(pick.label);
}
const guessRankOfPicked: number = (pick as IDetectedLanguageQuickPickItem).guessRank ?? -1;
// If we detected languages and they didn't choose the top detected language (which should also be the active language if automatic detection is enabled)
// then the automatic language detection was likely wrong and the user is correcting it. In this case, we want telemetry.
if (detectedLanguages.length && guessRankOfPicked !== 0) {
this.telemetryService.publicLog2<IAutomaticLanguageDetectionLikelyWrongData, AutomaticLanguageDetectionLikelyWrongClassification>(AutomaticLanguageDetectionLikelyWrongId, {
// For languages that weren't guessed, the guessRankOfPicked will be -1. This detail tells us if the user chose the language that was guessed or not.
choseOtherGuessedLanguage: guessRankOfPicked !== -1,
currentLanguageId: currentLanguageId ?? 'unknown',
nextLanguageId: languageSelection?.languageIdentifier.language ?? 'unknown'
});
if (resource) {
// fire and forget to not slow things down
this.languageDetectionService.detectLanguage(resource).then(detectedModeId => {
const chosenModeId = this.modeService.getModeIdForLanguageName(pick.label.toLowerCase()) || 'unknown';
if (detectedModeId === currentModeId && currentModeId !== chosenModeId) {
// If they didn't choose the detected language (which should also be the active language if automatic detection is enabled)
// then the automatic language detection was likely wrong and the user is correcting it. In this case, we want telemetry.
this.telemetryService.publicLog2<IAutomaticLanguageDetectionLikelyWrongData, AutomaticLanguageDetectionLikelyWrongClassification>(AutomaticLanguageDetectionLikelyWrongId, {
currentLanguageId: currentLanguageId ?? 'unknown',
nextLanguageId: pick.label
});
}
});
}
}
// Change mode
......
......@@ -27,16 +27,6 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker {
private _loadFailed: boolean = false;
public async detectLanguage(uri: string): Promise<string | undefined> {
const stopWatch = new StopWatch(true);
for await (const language of this.detectLanguagesImpl(uri)) {
stopWatch.stop();
this._host.fhr('sendTelemetryEvent', [[language.languageId], [language.confidence], stopWatch.elapsed()]);
return language.languageId;
}
return undefined;
}
public async detectLanguages(uri: string): Promise<string[]> {
const languages: string[] = [];
const confidences: number[] = [];
const stopWatch = new StopWatch(true);
......@@ -46,8 +36,11 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker {
}
stopWatch.stop();
this._host.fhr('sendTelemetryEvent', [languages, confidences, stopWatch.elapsed()]);
return languages;
if (languages.length) {
this._host.fhr('sendTelemetryEvent', [languages, confidences, stopWatch.elapsed()]);
return languages[0];
}
return undefined;
}
private async getModelOperations(): Promise<ModelOperations> {
......
......@@ -69,16 +69,6 @@ export class LanguageDetectionService extends Disposable implements ILanguageDet
}
return undefined;
}
async detectLanguages(resource: URI): Promise<string[]> {
const languages: Array<string | undefined> = await this._languageDetectionWorkerClient.detectLanguages(resource);
for (let i = 0; i < languages.length; i++) {
const modeId = this.getModeId(languages[i]);
languages[i] = modeId ? modeId : undefined;
}
return languages.filter(<T>(l?: T): l is T => Boolean(l));
}
}
export interface IWorkerClient<W> {
......@@ -196,10 +186,6 @@ export class LanguageDetectionWorkerClient extends EditorWorkerClient {
await this._withSyncedResources([resource]);
return (await this._getProxy()).detectLanguage(resource.toString());
}
public async detectLanguages(resource: URI): Promise<string[]> {
await this._withSyncedResources([resource]);
return (await this._getProxy()).detectLanguages(resource.toString());
}
}
registerSingleton(ILanguageDetectionService, LanguageDetectionService);
......@@ -22,12 +22,6 @@ export interface ILanguageDetectionService {
* @returns the language mode for the given resource or undefined if the model is not confident enough.
*/
detectLanguage(resource: URI): Promise<string | undefined>;
/**
* @param resource The resource to detect the language for.
* @returns all possible language modes detected in this resource.
*/
detectLanguages(resource: URI): Promise<string[]>;
}
//#region Telemetry events
......@@ -35,13 +29,11 @@ export interface ILanguageDetectionService {
export const AutomaticLanguageDetectionLikelyWrongId = 'automaticlanguagedetection.likelywrong';
export interface IAutomaticLanguageDetectionLikelyWrongData {
choseOtherGuessedLanguage: boolean;
currentLanguageId: string;
nextLanguageId: string;
}
export type AutomaticLanguageDetectionLikelyWrongClassification = {
choseOtherGuessedLanguage: { classification: 'SystemMetaData', purpose: 'FeatureInsight' },
currentLanguageId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' },
nextLanguageId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册