mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-22 01:25:38 -05:00
Add notebook extension support for .NET Interactive. (#18334)
* Also updated kernel dropdown to only include SQL aliased kernels when using SQL notebook provider.
This commit is contained in:
@@ -12,7 +12,12 @@
|
||||
<div #editor class="editor"></div>
|
||||
</div>
|
||||
</div>
|
||||
<collapse-component *ngIf="cellModel.cellType === 'code' && cellModel.source && cellModel.source.length > 1" [cellModel]="cellModel" [activeCellId]="activeCellId"></collapse-component>
|
||||
<div style="display: flex; flex-flow: row; justify-content: flex-end;">
|
||||
<collapse-component *ngIf="cellModel.cellType === 'code' && cellModel.source && cellModel.source.length > 1" [cellModel]="cellModel" [activeCellId]="activeCellId"></collapse-component>
|
||||
<div #cellLanguage class="cellLanguage" *ngIf="cellModel.cellType === 'code' && cellModel.language">
|
||||
{{cellModel.displayLanguage}}
|
||||
</div>
|
||||
</div>
|
||||
<div #parameter class="parameter" *ngIf="cellModel.cellType === 'code' && cellModel.isParameter">
|
||||
<span>{{parametersText}}</span>
|
||||
</div>
|
||||
|
||||
@@ -48,6 +48,7 @@ const DEFAULT_OR_LOCAL_CONTEXT_ID = '-1';
|
||||
export class CodeComponent extends CellView implements OnInit, OnChanges {
|
||||
@ViewChild('toolbar', { read: ElementRef }) private toolbarElement: ElementRef;
|
||||
@ViewChild('editor', { read: ElementRef }) private codeElement: ElementRef;
|
||||
@ViewChild('cellLanguage', { read: ElementRef }) private languageElement: ElementRef;
|
||||
|
||||
public get cellModel(): ICellModel {
|
||||
return this._cellModel;
|
||||
@@ -265,6 +266,12 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
|
||||
this.setFocusAndScroll();
|
||||
}
|
||||
}));
|
||||
this._register(this.cellModel.onLanguageChanged(language => {
|
||||
let nativeElement = <HTMLElement>this.languageElement.nativeElement;
|
||||
nativeElement.innerText = this.cellModel.displayLanguage;
|
||||
this.updateLanguageMode();
|
||||
this._changeRef.detectChanges();
|
||||
}));
|
||||
this._register(this.cellModel.onCollapseStateChanged(isCollapsed => {
|
||||
this.onCellCollapse(isCollapsed);
|
||||
}));
|
||||
@@ -379,8 +386,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
|
||||
this.cellModel.setOverrideLanguage(magic.language);
|
||||
this.updateLanguageMode();
|
||||
}
|
||||
} else {
|
||||
this.cellModel.setOverrideLanguage(undefined);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -98,6 +98,10 @@ code-component .carbon-taskbar .codicon.hideIcon.execCountHundred {
|
||||
margin-left: -6px;
|
||||
}
|
||||
|
||||
code-component collapse-component {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
code-component .hide-component-button {
|
||||
height: 16px;
|
||||
width: 100%;
|
||||
@@ -106,6 +110,15 @@ code-component .hide-component-button {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-color: transparent;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
code-component .cellLanguage {
|
||||
padding: 2px 15px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
code-component .parameter {
|
||||
|
||||
@@ -40,6 +40,7 @@ import { LocalContentManager } from 'sql/workbench/services/notebook/common/loca
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Extensions as LanguageAssociationExtensions, ILanguageAssociationRegistry } from 'sql/workbench/services/languageAssociation/common/languageAssociation';
|
||||
import { NotebookLanguage } from 'sql/workbench/common/constants';
|
||||
import { DotnetInteractiveLabel, DotnetInteractiveJupyterLabelPrefix, DotnetInteractiveJupyterLanguagePrefix, DotnetInteractiveLanguagePrefix } from 'sql/workbench/api/common/notebooks/notebookUtils';
|
||||
|
||||
export type ModeViewSaveHandler = (handle: number) => Thenable<boolean>;
|
||||
const languageAssociationRegistry = Registry.as<ILanguageAssociationRegistry>(LanguageAssociationExtensions.LanguageAssociations);
|
||||
@@ -351,7 +352,8 @@ export abstract class NotebookInput extends EditorInput implements INotebookInpu
|
||||
connectionProviderIds: kernel.connectionProviderIds,
|
||||
name: kernel.name,
|
||||
displayName: kernel.displayName,
|
||||
notebookProvider: kernel.notebookProvider
|
||||
notebookProvider: kernel.notebookProvider,
|
||||
supportedLanguages: kernel.supportedLanguages
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -540,6 +542,26 @@ export class NotebookEditorContentLoader implements IContentLoader {
|
||||
|
||||
async loadContent(): Promise<azdata.nb.INotebookContents> {
|
||||
let notebookEditorModel = await this.notebookInput.resolve();
|
||||
return this.contentManager.deserializeNotebook(notebookEditorModel.contentString);
|
||||
let notebookContents = await this.contentManager.deserializeNotebook(notebookEditorModel.contentString);
|
||||
|
||||
// Special case .NET Interactive kernel spec to handle inconsistencies between notebook providers and jupyter kernel specs
|
||||
if (notebookContents.metadata?.kernelspec?.display_name?.startsWith(DotnetInteractiveJupyterLabelPrefix)) {
|
||||
notebookContents.metadata.kernelspec.oldDisplayName = notebookContents.metadata.kernelspec.display_name;
|
||||
notebookContents.metadata.kernelspec.display_name = DotnetInteractiveLabel;
|
||||
|
||||
let kernelName = notebookContents.metadata.kernelspec.name;
|
||||
let baseLanguageName = kernelName.replace(DotnetInteractiveJupyterLanguagePrefix, '');
|
||||
if (baseLanguageName === 'powershell') {
|
||||
baseLanguageName = 'pwsh';
|
||||
}
|
||||
let languageName = `${DotnetInteractiveLanguagePrefix}${baseLanguageName}`;
|
||||
|
||||
notebookContents.metadata.kernelspec.oldLanguage = notebookContents.metadata.kernelspec.language;
|
||||
notebookContents.metadata.kernelspec.language = languageName;
|
||||
|
||||
notebookContents.metadata.language_info.oldName = notebookContents.metadata.language_info.name;
|
||||
notebookContents.metadata.language_info.name = languageName;
|
||||
}
|
||||
return notebookContents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +410,9 @@ registerComponentType({
|
||||
mimeTypes: [
|
||||
'text/plain',
|
||||
'application/vnd.jupyter.stdout',
|
||||
'application/vnd.jupyter.stderr'
|
||||
'application/vnd.jupyter.stderr',
|
||||
'application/vnd.code.notebook.stdout',
|
||||
'application/vnd.code.notebook.stderr'
|
||||
],
|
||||
rank: 120,
|
||||
safe: true,
|
||||
@@ -418,6 +420,19 @@ registerComponentType({
|
||||
selector: MimeRendererComponent.SELECTOR
|
||||
});
|
||||
|
||||
/**
|
||||
* A mime renderer component for VS Code Notebook error data.
|
||||
*/
|
||||
registerComponentType({
|
||||
mimeTypes: [
|
||||
'application/vnd.code.notebook.error'
|
||||
],
|
||||
rank: 121,
|
||||
safe: true,
|
||||
ctor: MimeRendererComponent,
|
||||
selector: MimeRendererComponent.SELECTOR
|
||||
});
|
||||
|
||||
/**
|
||||
* A placeholder component for deprecated rendered JavaScript.
|
||||
*/
|
||||
|
||||
@@ -67,7 +67,8 @@ class TestNotebookModel extends NotebookModelStub {
|
||||
name: 'StandardKernel1',
|
||||
displayName: 'StandardKernel1',
|
||||
connectionProviderIds: ['Kernel1 connection 1', 'Kernel1 connection2'],
|
||||
notebookProvider: 'kernel provider1'
|
||||
notebookProvider: 'kernel provider1',
|
||||
supportedLanguages: ['python']
|
||||
}
|
||||
],
|
||||
[
|
||||
@@ -76,7 +77,8 @@ class TestNotebookModel extends NotebookModelStub {
|
||||
name: 'StandardKernel2',
|
||||
displayName: 'StandardKernel2',
|
||||
connectionProviderIds: ['Kernel1 connection 2', 'Kernel1 connection2'],
|
||||
notebookProvider: 'kernel provider2'
|
||||
notebookProvider: 'kernel provider2',
|
||||
supportedLanguages: ['python']
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -40,7 +40,8 @@ suite('Notebook Input', function (): void {
|
||||
name: 'TestName',
|
||||
displayName: 'TestDisplayName',
|
||||
connectionProviderIds: ['TestId'],
|
||||
notebookProvider: testProvider
|
||||
notebookProvider: testProvider,
|
||||
supportedLanguages: ['python']
|
||||
}]);
|
||||
});
|
||||
let testManager: ISerializationManager = {
|
||||
@@ -129,12 +130,14 @@ suite('Notebook Input', function (): void {
|
||||
name: 'TestName1',
|
||||
displayName: 'TestDisplayName1',
|
||||
connectionProviderIds: ['TestId1'],
|
||||
notebookProvider: 'TestProvider'
|
||||
notebookProvider: 'TestProvider',
|
||||
supportedLanguages: ['python']
|
||||
}, {
|
||||
name: 'TestName2',
|
||||
displayName: 'TestDisplayName2',
|
||||
connectionProviderIds: ['TestId2'],
|
||||
notebookProvider: 'TestProvider'
|
||||
notebookProvider: 'TestProvider',
|
||||
supportedLanguages: ['python']
|
||||
}];
|
||||
untitledNotebookInput.standardKernels = testKernels;
|
||||
assert.deepStrictEqual(untitledNotebookInput.standardKernels, testKernels);
|
||||
|
||||
@@ -236,7 +236,8 @@ suite.skip('NotebookService:', function (): void {
|
||||
standardKernels: [{
|
||||
name: 'kernel1',
|
||||
connectionProviderIds: [],
|
||||
displayName: 'Kernel 1'
|
||||
displayName: 'Kernel 1',
|
||||
supportedLanguages: ['python']
|
||||
}],
|
||||
provider: 'otherProvider'
|
||||
};
|
||||
|
||||
@@ -21,12 +21,14 @@ suite('notebookUtils', function (): void {
|
||||
const testKernel: nb.IStandardKernel = {
|
||||
name: 'testName',
|
||||
displayName: 'testDisplayName',
|
||||
connectionProviderIds: ['testId1', 'testId2']
|
||||
connectionProviderIds: ['testId1', 'testId2'],
|
||||
supportedLanguages: ['python']
|
||||
};
|
||||
const sqlStandardKernel: nb.IStandardKernel = {
|
||||
name: notebookConstants.SQL,
|
||||
displayName: notebookConstants.SQL,
|
||||
connectionProviderIds: [notebookConstants.SQL_CONNECTION_PROVIDER]
|
||||
connectionProviderIds: [notebookConstants.SQL_CONNECTION_PROVIDER],
|
||||
supportedLanguages: ['sql']
|
||||
};
|
||||
|
||||
function setupMockNotebookService() {
|
||||
@@ -108,7 +110,8 @@ suite('notebookUtils', function (): void {
|
||||
name: 'testName',
|
||||
displayName: 'testDisplayName',
|
||||
connectionProviderIds: ['testId1', 'testId2'],
|
||||
notebookProvider: 'testProvider'
|
||||
notebookProvider: 'testProvider',
|
||||
supportedLanguages: ['python']
|
||||
}]);
|
||||
});
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import { ConnectionProfile } from 'sql/platform/connection/common/connectionProf
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryTextEditor';
|
||||
import { IContextViewProvider, IDelegate } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { IEditorInput, IEditorPane } from 'vs/workbench/common/editor';
|
||||
import { INotebookShowOptions } from 'sql/workbench/api/common/sqlExtHost.protocol';
|
||||
import { NotebookViewsExtension } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension';
|
||||
import { INotebookView, INotebookViewCell, INotebookViewMetadata, INotebookViews } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViews';
|
||||
@@ -235,6 +235,9 @@ export class ServerManagerStub implements nb.ServerManager {
|
||||
}
|
||||
|
||||
export class NotebookServiceStub implements INotebookService {
|
||||
createNotebookInput(options: INotebookShowOptions, resource?: UriComponents): Promise<IEditorInput> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
_serviceBrand: undefined;
|
||||
get onNotebookEditorAdd(): vsEvent.Event<INotebookEditor> {
|
||||
throw new Error('Method not implemented.');
|
||||
|
||||
Reference in New Issue
Block a user