Change:
Issue Type: <bBug</bto something like . a new tab. The tab should have the Markdown icon, but it has the Plain Text icon. If you move to another tab then back, the icon will be updated. This only started happening when I updated to 1.3, and it's still happening in Insiders. I've got no extensions or settings (other than ) set. VS Code version: Code - Insiders 1.31.0-insider (, 2018-12-21T06:14:53.023Z) OS version: Darwin x64 18.2.0 <!-- generated by issue reporter --
This is a consequence of adopting : When the tab opens we immediately render the icon, but the resource only gets the mode associated after a on the end of the tick.
via

Discussion:
// Get the path and name of the resource. For data-URIs, we need to parse specially let name: string | undefined; <del> let path: string | undefined; </del> if (resource.scheme === Schemas.data) { const metadata = DataUri.parseMetaData(resource); name = metadata.get(DataUri.META_DATA_LABEL); <del> path = name; </del> } else { name = cssEscape(basenameOrAuthority(resource).toLowerCase()); <del> path = resource.path.toLowerCase(); </del> } // Folders

classes.push(`ext-file-icon`); // extra segment to increase file-ext score } <del> // Configured Language let configuredLangId: string | null = getConfiguredLangId(modelService, modeService, resource); configuredLangId = configuredLangId || (path ? modeService.getModeIdByFilepathOrFirstLine(path) : null); if (configuredLangId) { classes.push(`${cssEscape(configuredLangId)}-lang-file-icon`); </del> <ins> // Detected Mode const detectedModeId = detectModeId(modelService, modeService, resource); if (detectedModeId) { classes.push(`${cssEscape(detectedModeId)}-lang-file-icon`); </ins> } } } return classes; } <del> export function getConfiguredLangId(modelService: IModelService, modeService: IModeService, resource: uri): string | null { let configuredLangId: string | null = null; if (resource) { let modeId: string | null = null; </del> <ins> export function detectModeId(modelService: IModelService, modeService: IModeService, resource: uri): string | null { if (!resource) { return null; // we need a resource at least } </ins> <del> // Data URI: check for encoded metadata if (resource.scheme === Schemas.data) { const metadata = DataUri.parseMetaData(resource); const mime = metadata.get(DataUri.META_DATA_MIME); </del> <ins> let modeId: string | null = null; </ins> <del> if (mime) { modeId = modeService.getModeId(mime); } } </del> <ins> // Data URI: check for encoded metadata if (resource.scheme === Schemas.data) { const metadata = DataUri.parseMetaData(resource); const mime = metadata.get(DataUri.META_DATA_MIME); </ins> <del> // Any other URI: check for model if existing else { const model = modelService.getModel(resource); if (model) { modeId = model.getLanguageIdentifier().language; } </del> <ins> if (mime) { modeId = modeService.getModeId(mime); </ins> } <ins> } </ins> <del> if (modeId && modeId !== PLAINTEXT_MODE_ID) { configuredLangId = modeId; // only take if the mode is specific (aka no just plain text) </del> <ins> // Any other URI: check for model if existing else { const model = modelService.getModel(resource); if (model) { modeId = model.getModeId(); </ins> } } <del> return configuredLangId; </del> <ins> // only take if the mode is specific (aka no just plain text) if (modeId && modeId !== PLAINTEXT_MODE_ID) { return modeId; } // otherwise fallback to path based detection let path: string | undefined; if (resource.scheme === Schemas.data) { const metadata = DataUri.parseMetaData(resource); path = metadata.get(DataUri.META_DATA_LABEL); } else { path = resource.path.toLowerCase(); } if (path) { return modeService.getModeIdByFilepathOrFirstLine(path); } return null; // finally - we do not know the mode id </ins> } export function cssEscape(val: string): string {

import { IThemeService } from 'vs/platform/theme/common/themeService'; import { Event, Emitter } from 'vs/base/common/event'; import { ILabelService } from 'vs/platform/label/common/label'; <del> import { getIconClasses, getConfiguredLangId } from 'vs/editor/common/services/getIconClasses'; </del> <ins> import { getIconClasses, detectModeId } from 'vs/editor/common/services/getIconClasses'; </ins> import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { withNullAsUndefined } from 'vs/base/common/types';

return; // ignore transitions in files from no mode to specific mode because this happens each time a model is created } <del> this._widgets.forEach(widget => widget.notifyModelModeChanged(e)); </del> <ins> this._widgets.forEach(widget => widget.notifyModelModeChanged(e.model)); })); // notify when model is added this._register(this.modelService.onModelAdded(model => { if (!model.uri) { return; // we need the resource to compare } this._widgets.forEach(widget => widget.notifyModelAdded(model)); </ins> })); // notify when file decoration changes

private label?: IResourceLabelProps; private options?: IResourceLabelOptions; private computedIconClasses?: string[]; <del> private lastKnownConfiguredLangId?: string; </del> <ins> private lastKnownDetectedModeId?: string; </ins> private computedPathLabel?: string; private needsRedraw?: Redraw;

} } <del> notifyModelModeChanged(e: { model: ITextModel; oldModeId: string; }): void { </del> <ins> notifyModelModeChanged(model: ITextModel): void { this.handleModelEvent(model); } notifyModelAdded(model: ITextModel): void { this.handleModelEvent(model); } private handleModelEvent(model: ITextModel): void { </ins> if (!this.label || !this.label.resource) { return; // only update if label exists } <del> if (e.model.uri.toString() === this.label.resource.toString()) { if (this.lastKnownConfiguredLangId !== e.model.getLanguageIdentifier().language) { </del> <ins> if (model.uri.toString() === this.label.resource.toString()) { if (this.lastKnownDetectedModeId !== model.getModeId()) { </ins> this.render(true); // update if the language id of the model has changed from our last known state } }

clear(): void { this.label = undefined; this.options = undefined; <del> this.lastKnownConfiguredLangId = undefined; </del> <ins> this.lastKnownDetectedModeId = undefined; </ins> this.computedIconClasses = undefined; this.computedPathLabel = undefined;

} if (this.label) { <del> const configuredLangId = this.label.resource ? withNullAsUndefined(getConfiguredLangId(this.modelService, this.modeService, this.label.resource)) : undefined; if (this.lastKnownConfiguredLangId !== configuredLangId) { </del> <ins> const detectedModeId = this.label.resource ? withNullAsUndefined(detectModeId(this.modelService, this.modeService, this.label.resource)) : undefined; if (this.lastKnownDetectedModeId !== detectedModeId) { </ins> clearIconCache = true; <del> this.lastKnownConfiguredLangId = configuredLangId; </del> <ins> this.lastKnownDetectedModeId = detectedModeId; </ins> } }

this.label = undefined; this.options = undefined; <del> this.lastKnownConfiguredLangId = undefined; </del> <ins> this.lastKnownDetectedModeId = undefined; </ins> this.computedIconClasses = undefined; this.computedPathLabel = undefined; }