Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AddNewLanguageSupport]:Add Csharp Language Support #76

Merged
merged 8 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions l10n/bundle.l10n.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"Optimize Code": "优化代码",
"Fix Code": "修复代码",
"Quick Chat": "快速聊天",
"AutoMethod": "填充当前方法",
"Optimize the code": "请优化下面的代码",
"How do I fix this problem in the above code?": "请帮我修复下面代码中的问题:",
"I got the following error, can you please help explain how to fix it?": "我遇到了以下错误,请帮我解释如何修复它?",
Expand Down
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,16 @@
"optimizeCode",
"autoComment",
"autoTest",
"customAction"
"customAction",
"AutoMethod"
]
},
"uniqueItems": true,
"default": [
"quickChat",
"autoTest",
"autoComment"
"autoComment",
"AutoMethod"
],
"description": "%configuration.codelensDisplayItems.description%",
"order": 4
Expand Down Expand Up @@ -644,6 +646,11 @@
"command": "autodev.codelens.autoComment",
"title": "%command.autoComment.title%"
},
{
"command": "autodev.codelens.CodeCompletions",
"title": "%command.CodeCompletions.title%"
},

{
"command": "autodev.codelens.autoTest",
"title": "%command.autoTest.title%"
Expand Down
2 changes: 1 addition & 1 deletion package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@
"command.openSettings.title": "Open Settings",
"command.showTutorial.title": "Show Tutorial",
"command.feedback.title": "Feedback",

"command.quickChat.title": "Quick Chat",
"command.AutoMethod.title": "Generate Method Codes",
"command.explainCode.title": "Explain Code",
"command.optimizeCode.title": "Optimize Code",
"command.quickFix.title": "Quick Fix",
Expand Down
1 change: 1 addition & 0 deletions package.nls.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"command.optimizeCode.title": "优化代码",
"command.quickFix.title": "快速修复",
"command.autoComment.title": "生成注释",
"command.AutoMethod.title":"填充当前方法",
"command.autoTest.title": "生成测试",

"command.openSettings.title": "打开设置",
Expand Down
17 changes: 17 additions & 0 deletions prompts/genius/en/code/auto-method.vm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Write documentation for user's given ${context.language} code.
#if($context.chatContext.length > 0 )
${context.chatContext}
#end
#if($context.forbiddenRules.length > 0)
${context.forbiddenRules}
#end
- Start your documentation with ${context.startSymbol} here, and ends with `${context.endSymbol}`.
Here is User's code:
```${context.language}
${context.code}
```
#if($context.originalComments.length > 0)
Here is code Origin comment: ${context.originalComments}
Please according to the code to update documentation.
#end
Please write documentation for user's code inside the Markdown code block.
1 change: 0 additions & 1 deletion prompts/genius/zh-cn/code/auto-doc.vm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ ${context.forbiddenRules}
Here is User's code:
```${context.language}
${context.code}
```

Please write documentation for this code inside the Markdown code block.
14 changes: 14 additions & 0 deletions prompts/genius/zh-cn/code/auto-method.vm
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Write documentation for user's given ${context.language} code.
#if($context.chatContext.length > 0 )
${context.chatContext}
#end
#if($context.forbiddenRules.length > 0)
${context.forbiddenRules}
#end
- Start your documentation with ${context.startSymbol} here, and ends with `${context.endSymbol}`.
Here is User's code:
```${context.language}
${context.code}
```

Please write documentation for this code inside the Markdown code block.
6 changes: 6 additions & 0 deletions src/AutoDevExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { logger } from 'base/common/log/log';

import { AutoDocActionExecutor } from './action/autodoc/AutoDocActionExecutor';
import { AutoTestActionExecutor } from './action/autotest/AutoTestActionExecutor';
import { AutoMethodActionExecutor } from './action/autoMethod/AutoMethodActionExecutor';

import {
registerAutoDevProviders,
registerCodeLensProvider,
Expand Down Expand Up @@ -42,6 +44,7 @@ import { TemplateRender } from './prompt-manage/template/TemplateRender';
import { IProjectService } from './ProviderTypes';
import { ToolchainContextManager } from './toolchain-context/ToolchainContextManager';


@injectable()
export class AutoDevExtension {
// Vscode
Expand Down Expand Up @@ -223,6 +226,9 @@ export class AutoDevExtension {
executeAutoDocAction(document: TextDocument, nameElement: NamedElement, edit?: WorkspaceEdit) {
return new AutoDocActionExecutor(this, document, nameElement, edit).execute();
}
executeAutoMethodAction(document: TextDocument, nameElement: NamedElement, edit?: WorkspaceEdit) {
return new AutoMethodActionExecutor(this, document, nameElement, edit).execute();
}

executeAutoTestAction(document: TextDocument, nameElement: NamedElement, edit?: WorkspaceEdit) {
return new AutoTestActionExecutor(this, document, nameElement, edit).execute();
Expand Down
2 changes: 2 additions & 0 deletions src/ProviderContainer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ import { JavaScriptContextProvider } from './toolchain-context/framework/javascr
import { SpringContextProvider } from './toolchain-context/framework/jvm/SpringContextProvider';
import { ToolchainContextProvider } from './toolchain-context/ToolchainContextProvider';
import { JavaVersionProvider } from './toolchain-context/version/JavaVersionProvider';
import { AutoMethodActionCreator } from './action/autoMethod/AutoMethodActionCreator';

// Action Register
providerContainer.bind(IActionCreator).to(AutoDocActionCreator);
providerContainer.bind(IActionCreator).to(AutoMethodActionCreator);
providerContainer.bind(IActionCreator).to(AutoTestActionCreator);
providerContainer.bind(IActionCreator).to(GenApiDataActionCreator);

Expand Down
2 changes: 2 additions & 0 deletions src/ProviderLanguageProfile.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import { PythonProfile } from './code-context/python/PythonProfile';
import { RustProfile } from './code-context/rust/RustProfile';
import { TypeScriptProfile } from './code-context/typescript/TypeScriptProfile';
import { ILanguageProfile } from './ProviderTypes';
import { CsharpProfile } from './code-context/csharp/CsharpProfile';

const languageContainer = new Container();

languageContainer.bind(ILanguageProfile).to(JavaProfile);
languageContainer.bind(ILanguageProfile).to(TypeScriptProfile);
languageContainer.bind(ILanguageProfile).to(GolangProfile);
languageContainer.bind(ILanguageProfile).to(PythonProfile);
languageContainer.bind(ILanguageProfile).to(CsharpProfile)
languageContainer.bind(ILanguageProfile).to(RustProfile);

export { languageContainer };
40 changes: 40 additions & 0 deletions src/action/autoMethod/AutoMethodActionCreator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { injectable } from 'inversify';
import vscode from 'vscode';

import { NamedElement } from '../../editor/ast/NamedElement';
import { ActionCreatorContext } from '../_base/ActionCreatorContext';
import { CodeActionCreator } from '../_base/CodeActionCreator';
import { CMD_GEN_CODE_METHOD_COMPLETIONS } from 'base/common/configuration/configuration';

@injectable()
export class AutoMethodActionCreator extends CodeActionCreator {
static readonly providedCodeActionKinds = [vscode.CodeActionKind.RefactorRewrite];

isApplicable(creatorContext: ActionCreatorContext): boolean {
return true;
}

buildClassAction(context: ActionCreatorContext, elementBlock: NamedElement) {
const title = `AutoDoc for class \`${elementBlock.identifierRange.text}\` (AutoDev)`;
return this.createMethodAction(title, context.document, elementBlock);
}

buildMethodAction(context: ActionCreatorContext, elementBlock: NamedElement): vscode.CodeAction {
const title = `AutoDoc for method \`${elementBlock.identifierRange.text}\` (AutoDev)`;
return this.createMethodAction(title, context.document, elementBlock);
}

private createMethodAction(title: string, document: vscode.TextDocument, block: NamedElement): vscode.CodeAction {
const codeAction = new vscode.CodeAction(title, AutoMethodActionCreator.providedCodeActionKinds[0]);

codeAction.isPreferred = false;
codeAction.edit = new vscode.WorkspaceEdit();
codeAction.command = {
command: CMD_GEN_CODE_METHOD_COMPLETIONS,
title: title,
arguments: [document, block, codeAction.edit],
};

return codeAction;
}
}
122 changes: 122 additions & 0 deletions src/action/autoMethod/AutoMethodActionExecutor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { AutoDevExtension } from 'src/AutoDevExtension';
import { CancellationTokenSource, Position, TextDocument, WorkspaceEdit } from 'vscode';

import { ChatMessageRole, IChatMessage } from 'base/common/language-models/languageModels';
import { LanguageModelsService } from 'base/common/language-models/languageModelsService';
import { LANGUAGE_BLOCK_COMMENT_MAP } from 'base/common/languages/docstring';
import { log } from 'base/common/log/log';
import { MarkdownTextProcessor } from 'base/common/markdown/MarkdownTextProcessor';
import { StreamingMarkdownCodeBlock } from 'base/common/markdown/StreamingMarkdownCodeBlock';

import { type NamedElement } from '../../editor/ast/NamedElement';
import { insertCodeByRange, selectCodeInRange } from '../../editor/ast/PositionUtil';
import { AutoDevStatus, AutoDevStatusManager } from '../../editor/editor-api/AutoDevStatusManager';
import { ActionType } from '../../prompt-manage/ActionType';
import { PromptManager } from '../../prompt-manage/PromptManager';
import { CreateToolchainContext } from '../../toolchain-context/ToolchainContextProvider';
import { ActionExecutor } from '../_base/ActionExecutor';
import { AutoDocTemplateContext } from '../autodoc/AutoDocTemplateContext';
import { AutoMethodTemplateContext } from './AutoMethodTemplateContext';

export class AutoMethodActionExecutor implements ActionExecutor {
type: ActionType = ActionType.AutoDoc;

private lm: LanguageModelsService;
private promptManager: PromptManager;
private statusBarManager: AutoDevStatusManager;

private document: TextDocument;
private range: NamedElement;
private edit?: WorkspaceEdit;
private language: string;

constructor(autodev: AutoDevExtension, document: TextDocument, range: NamedElement, edit?: WorkspaceEdit) {
this.lm = autodev.lm;
this.promptManager = autodev.promptManager;
this.statusBarManager = autodev.statusBarManager;

this.document = document;
this.range = range;
this.edit = edit;
this.language = document.languageId;
}

async execute() {
const document = this.document;
const range = this.range;
const language = document.languageId;

const startSymbol = LANGUAGE_BLOCK_COMMENT_MAP[language]!.start;
const endSymbol = LANGUAGE_BLOCK_COMMENT_MAP[language]!.end;

const templateContext: AutoMethodTemplateContext = {
language: language,
startSymbol: startSymbol,
endSymbol: endSymbol,
code: document.getText(range.blockRange),
forbiddenRules: [],
// 原有代码块
originalMethodCodes: [],
};

if (range.commentRange) {
templateContext.originalMethodCodes.push(document.getText(range.commentRange));
}

this.statusBarManager.setStatus(AutoDevStatus.InProgress);

selectCodeInRange(range.blockRange.start, range.blockRange.end);
if (range.commentRange) {
selectCodeInRange(range.commentRange.start, range.commentRange.end);
}

const creationContext: CreateToolchainContext = {
action: 'AutoMethodAction',
filename: document.fileName,
language: language,

content: document.getText(),
element: range,
};

const contextItems = await this.promptManager.collectToolchain(creationContext);
if (contextItems.length > 0) {
templateContext.chatContext = contextItems.map(item => item.text).join('\n - ');
}

let content = await this.promptManager.generateInstruction(ActionType.AutoMethod, templateContext);
log(`request: ${content}`);

let msg: IChatMessage = {
role: ChatMessageRole.User,
content: content,
};

try {
const doc = await this.lm.chat([msg], {});

this.statusBarManager.setStatus(AutoDevStatus.Done);
const finalText = StreamingMarkdownCodeBlock.parse(doc).text;

log(`FencedCodeBlock parsed output: ${finalText}`);

let codestring = MarkdownTextProcessor.buildDocFromSuggestion(doc, startSymbol, endSymbol);

let startLine = range.blockRange.start.line;
let startChar = range.blockRange.start.character;

if (startLine === 0) {
startLine = 1;
}

// todo: add format by indent.

const textRange: Position = new Position(startLine - 1, startChar);
insertCodeByRange(textRange, codestring);
} catch (e) {
console.error(e);
this.statusBarManager.setStatus(AutoDevStatus.Error);
return;
}
}
}
9 changes: 9 additions & 0 deletions src/action/autoMethod/AutoMethodTemplateContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { TemplateContext } from '../../prompt-manage/template/TemplateContext';

export interface AutoMethodTemplateContext extends TemplateContext {
startSymbol: string;
endSymbol: string;
code: string;
forbiddenRules: string[];
originalMethodCodes: string[];
}
22 changes: 20 additions & 2 deletions src/action/providers/AutoDevCodeLensProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
CMD_CODELENS_QUICK_CHAT,
CMD_CODELENS_SHOW_CUSTOM_ACTION,
CMD_SHOW_CODELENS_DETAIL_QUICKPICK,
CMD_CODELENS_SHOW_CODE_METHOD_COMPLETIONS,
} from 'base/common/configuration/configuration';
import { ConfigurationService } from 'base/common/configuration/configurationService';
import { isFileTooLarge } from 'base/common/files/files';
Expand All @@ -35,8 +36,9 @@ import { ILanguageServiceProvider } from 'base/common/languages/languageService'
import { logger } from 'base/common/log/log';

import { type AutoDevExtension } from '../../AutoDevExtension';
import { CodeElementType } from 'src/editor/codemodel/CodeElementType';

type CodeLensItemType = 'quickChat' | 'explainCode' | 'optimizeCode' | 'autoComment' | 'autoTest' | 'customAction';
type CodeLensItemType = 'quickChat' | 'explainCode' | 'optimizeCode' | 'autoComment' | 'autoTest' | 'customAction'|'AutoMethod';

export class AutoDevCodeLensProvider implements CodeLensProvider {
private config: ConfigurationService;
Expand Down Expand Up @@ -123,6 +125,9 @@ export class AutoDevCodeLensProvider implements CodeLensProvider {
commands.registerCommand(CMD_CODELENS_SHOW_CUSTOM_ACTION, (document: TextDocument, nameElement: NamedElement) => {
autodev.executeCustomAction(document, nameElement);
}),
commands.registerCommand(CMD_CODELENS_SHOW_CODE_METHOD_COMPLETIONS, (document: TextDocument, nameElement: NamedElement) => {
autodev.executeAutoMethodAction(document, nameElement);
}),
];
}

Expand Down Expand Up @@ -153,6 +158,7 @@ export class AutoDevCodeLensProvider implements CodeLensProvider {
}

const elements = await this.parseToNamedElements(document);
// elements为空导致codelens组没有数据,无法生成codelens

if (token.isCancellationRequested || elements.length === 0) {
return [];
Expand Down Expand Up @@ -250,7 +256,6 @@ export class AutoDevCodeLensProvider implements CodeLensProvider {
}
continue;
}

if (type === 'customAction') {
if (hasCustomPromps) {
codelenses.push(
Expand All @@ -263,6 +268,19 @@ export class AutoDevCodeLensProvider implements CodeLensProvider {
}
continue;
}
if (type === 'AutoMethod') {
if (element.codeElementType==CodeElementType.Method) {
codelenses.push(
new CodeLens(element.identifierRange, {
title: l10n.t('AutoMethod'),
command: CMD_CODELENS_SHOW_CODE_METHOD_COMPLETIONS,
arguments: [document, element],
}),
);
}
continue;
}

}

result.push(codelenses);
Expand Down
Loading
Loading