Skip to content

Commit

Permalink
w
Browse files Browse the repository at this point in the history
sikaco committed Mar 28, 2023
1 parent b3cb874 commit 0c58959
Showing 7 changed files with 175 additions and 67 deletions.
59 changes: 30 additions & 29 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -3,33 +3,34 @@
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
},
{
"name": "Extension Tests",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js",
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "tasks: watch-tests"
}
]
"version": "0.2.0",
"configurations": [
// {
// "name": "Run Extension",
// "type": "extensionHost",
// "request": "launch",
// "args": ["--extensionDevelopmentPath=${workspaceFolder}"],
// "outFiles": ["${workspaceFolder}/dist/**/*.js"],
// "preLaunchTask": "${defaultBuildTask}"
// },
{
"name": "Launch Extension",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"runtimeExecutable": "${execPath}"
},
{
"name": "Extension Tests",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
],
"outFiles": ["${workspaceFolder}/out/**/*.js", "${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "tasks: watch-tests"
}
]
}
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
"Other"
],
"activationEvents": [],
"main": "./dist/extension.js",
"main": "./out/extension.js",
"contributes": {
"commands": [
{
@@ -21,16 +21,17 @@
},
"scripts": {
"vscode:prepublish": "pnpm run package",
"compile": "webpack",
"watch": "webpack --watch",
"package": "webpack --mode production --devtool hidden-source-map",
"compile-tests": "tsc -p . --outDir out",
"watch-tests": "tsc -p . -w --outDir out",
"pretest": "pnpm run compile-tests && pnpm run compile && pnpm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js",
"webpack": "webpack --mode development",
"webpack:watch": "webpack --mode development --watch"
"webpack:watch": "webpack --mode development --watch",
"compile": "tsc -watch -p ./",
"prepublish": "npm run compile",
"test": "npm run compile && node ./out/test/runTest.js"
},
"devDependencies": {
"@types/glob": "^8.1.0",
@@ -59,6 +60,7 @@
"dependencies": {
"@types/react": "^18.0.29",
"@types/react-dom": "^18.0.11",
"acorn": "^8.8.2",
"axios": "^1.3.4",
"prettier": "^2.8.7",
"react": "^18.2.0",
3 changes: 2 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/FloatingUI.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import * as React from 'react'
import * as vscode from 'vscode'

type MessageEvent = any

interface FloatingUIProps {
output: string
window: any
}

export const FloatingUI: React.FC<FloatingUIProps> = ({ output }) => {
export const FloatingUI: React.FC<FloatingUIProps> = ({ output, window }) => {
const [reviewOutput, setReviewOutput] = React.useState(output)

React.useEffect(() => {
152 changes: 127 additions & 25 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -2,35 +2,42 @@
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode'
import axios from 'axios'
import * as acorn from 'acorn'
import * as tsParser from '@typescript-eslint/parser'

import { createWebView } from './webview'

async function checkCode(webView: vscode.WebviewPanel) {
const activeEditor = vscode.window.activeTextEditor
if (!activeEditor) {
return
}
const functionName = getCurrentFunctionName(activeEditor)
if (!functionName) {
return
}

const code = getFunctionCode(activeEditor, functionName)
const gpt3Review = await getGPT3Review(code)

webView.webview.postMessage({
command: 'updateOutput',
content: gpt3Review
})
}

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "vscode-angel" is now active!')
// eslint-disable-next-line no-console
console.info('Congratulations, your extension "vscode-angel" is now active!')

const webView = createWebView(context)

setInterval(async () => {
const activeEditor = vscode.window.activeTextEditor
if (!activeEditor) {
return
}
const functionName = getCurrentFunctionName(activeEditor)
if (!functionName) {
return
}

const code = getFunctionCode(activeEditor, functionName)
const gpt3Review = await getGPT3Review(code)

webView.webview.postMessage({
command: 'updateOutput',
content: gpt3Review
})
checkCode(webView)
}, 10000)

// The command has been defined in the package.json file
@@ -43,17 +50,26 @@ export function activate(context: vscode.ExtensionContext) {
})

context.subscriptions.push(disposable)
}

// This method is called when your extension is deactivated
export function deactivate() { }

function getCurrentFunctionName(editor: vscode.TextEditor): string | null {
// 在此实现获取当前光标所在函数名称的逻辑
context.subscriptions.push(
vscode.workspace.onDidChangeTextDocument(async e => {
const editor = vscode.window.activeTextEditor
if (editor && e.document === editor.document) {
// const functionName = getCurrentFunctionName(editor)
// if (functionName) {
// const functionCode = getFunctionCode(editor, functionName)
// await fetchGpt3Review(functionCode)
// }
checkCode(webView)
}
})
)
}

function getFunctionCode(editor: vscode.TextEditor, functionName: string): string {
// 在此实现根据函数名称获取函数代码的逻辑
// This method is called when your extension is deactivated
export function deactivate() {
// eslint-disable-next-line no-console
console.log('extension ended.')
}

async function getGPT3Review(code: string): Promise<string> {
@@ -79,3 +95,89 @@ async function getGPT3Review(code: string): Promise<string> {
return '无法获取评价'
}
}

function getAst(document: vscode.TextDocument) {
const code = document.getText()
const languageId = document.languageId

let ast

if (languageId === 'javascript') {
ast = acorn.parse(code, { ecmaVersion: 2022, sourceType: 'module' })
} else if (languageId === 'typescript') {
ast = tsParser.parse(code, { sourceType: 'module' })
} else {
return null
}

return ast
}

// 在此实现获取当前光标所在函数名称的逻辑
function getCurrentFunctionName(editor: vscode.TextEditor): string | null {
const position = editor.selection.active
const document = editor.document
const ast = getAst(document)

if (!ast) {
return null
}

let functionName = null
const positionOffset = document.offsetAt(position)

function traverse(node: any, parentNode: any) {
if (
node.type === 'FunctionDeclaration' ||
node.type === 'FunctionExpression' ||
node.type === 'ArrowFunctionExpression'
) {
if (node.start <= positionOffset && node.end >= positionOffset) {
if (parentNode && parentNode.type === 'VariableDeclarator') {
functionName = parentNode.id.name
} else if (node.id) {
functionName = node.id.name
}
}
}
for (const key in node) {
if (typeof node[key] === 'object') {
traverse(node[key], node)
}
}
}
traverse(ast, null)
return functionName
}

// 在此实现根据函数名称获取函数代码的逻辑
function getFunctionCode(editor: vscode.TextEditor, functionName: string): string {
const document = editor.document
const ast = getAst(document)

if (!ast) {
return ''
}

let functionCode = ''

function traverse(node: any) {
if (
(node.type === 'FunctionDeclaration' && node.id && node.id.name === functionName) ||
(node.type === 'VariableDeclarator' && node.id && node.id.name === functionName)
) {
const startPosition = document.positionAt(node.start)
const endPosition = document.positionAt(node.end)
functionCode = document.getText(new vscode.Range(startPosition, endPosition))
}

for (const key in node) {
if (typeof node[key] === 'object') {
traverse(node[key])
}
}
}

traverse(ast)
return functionCode
}
11 changes: 5 additions & 6 deletions src/webview.tsx
Original file line number Diff line number Diff line change
@@ -4,8 +4,6 @@ import * as fs from 'fs'
import * as React from 'react'
import * as vscode from 'vscode'

import { FloatingUI } from './FloatingUI'

export function createWebView(context: vscode.ExtensionContext) {
const panel = vscode.window.createWebviewPanel(
'gpt3Review',
@@ -23,10 +21,11 @@ export function createWebView(context: vscode.ExtensionContext) {
message => {
switch (message.command) {
case 'updateOutput':
panel.webview.postMessage({
command: 'updateOutput',
content: message.content
})
// panel.webview.postMessage({
// command: 'updateOutput',
// content: message.content
// })
console.log('gpt3Review: ', message.content)
break
}
},
2 changes: 1 addition & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ const extensionConfig = {
entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
path: path.resolve(__dirname, 'out'),
filename: 'extension.js',
libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../[resource-path]'

0 comments on commit 0c58959

Please sign in to comment.