✨ feat(vscode): 代码阅读的词可以讲源码里别处的名字(Segment.refers):FastAPI 路径里的 {user_id} 讲函数的参数,单击参数时跟着高亮,⌘ + 点击跳到参数
This commit is contained in:
1 parent
25569fa506
commit
15790ce7c8
9 files changed
+82
-22
No files matched your search
@@ -19,4 +19,15 @@ describe('着色的词', () => {
|
||||
)
|
||||
expect(html).toBe('<span class="cr-role-keyword cr-colored" style="--color-dark:#fca130;--color-light:#b35f00">PUT</span><span class="cr-role-string"> /users</span>')
|
||||
})
|
||||
|
||||
it('讲别处名字的段(refers):data-offset 记那个名字的下标,⌘ + 点击、单击高亮都按它', () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<SegmentText segments={[
|
||||
{ text: '/users/', role: 'string', offset: 20 },
|
||||
{ text: 'user_id', role: 'variable', offset: 28, refers: { startIndex: 90, endIndex: 97 } },
|
||||
]}
|
||||
/>,
|
||||
)
|
||||
expect(html).toBe('<span class="cr-role-string" data-offset="20">/users/</span><span class="cr-role-variable" data-offset="90">user_id</span>')
|
||||
})
|
||||
})
|
||||
@@ -4,12 +4,12 @@ import type { GroupStyle, Inline, SegmentGroup } from './types'
|
||||
import { useContext } from 'react'
|
||||
import { DisplayNameContext, shownName } from './displayNames'
|
||||
import { KIND_ICON_COMPONENTS, KIND_ICONS } from './kindIcons'
|
||||
import { isCurrent, segmentOccurrence } from './occurrences'
|
||||
import { isCurrent, segmentOccurrence, sourceOf } from './occurrences'
|
||||
import { HighlightContext } from './useOccurrences'
|
||||
|
||||
/**
|
||||
* 按词性给每一段上色,颜色在 codeReader.css 的 .cr-role-* 里按主题切换,带自己颜色(color)的段用它(.cr-colored);带源码下标的名字记在 data-offset 上,
|
||||
* 跳到定义、高亮各处出现用;是眼下高亮着的名字的一处出现时 data-occurrence 标出底色,是当前那一处(点中的、用键盘跳到的)时
|
||||
* 按词性给每一段上色,颜色在 codeReader.css 的 .cr-role-* 里按主题切换,带自己颜色(color)的段用它(.cr-colored);带源码下标的名字记在 data-offset 上
|
||||
* (讲别处名字的段记那个名字的下标,见 sourceOf),跳到定义、高亮各处出现用;是眼下高亮着的名字的一处出现时 data-occurrence 标出底色,是当前那一处(点中的、用键盘跳到的)时
|
||||
* 再标 data-current。起了中文名的名字显示中文名(data-name),悬停看原名,定义处本身在后面淡淡写原名;下标照旧,跳到定义、高亮照常。
|
||||
* 框起来的一组词画成小框,框里的词同样处理。
|
||||
*/
|
||||
@@ -27,7 +27,7 @@ export function SegmentText({ segments }: { segments: Inline[] }): ReactElement
|
||||
key={index}
|
||||
className={piece.color ? `cr-role-${piece.role} cr-colored` : `cr-role-${piece.role}`}
|
||||
style={piece.color && { '--color-dark': piece.color.dark, '--color-light': piece.color.light } as CSSProperties}
|
||||
data-offset={piece.offset}
|
||||
data-offset={sourceOf(piece)?.start}
|
||||
data-occurrence={highlight && segmentOccurrence(piece, highlight.occurrences)}
|
||||
data-current={highlight && isCurrent(piece, highlight) ? '' : undefined}
|
||||
data-name={shown?.name}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createPythonAdapter } from '../../../src/codeReader/languages/python'
|
||||
import { WASM_DIR, withBlocks } from '../../../src/codeReader/testSupport'
|
||||
import { pythonZhTranslator } from '../../../src/codeReader/translators/pythonZh'
|
||||
import { DefinitionLinks } from './definitionLinks'
|
||||
import { clickAction, isCurrent, KEY_SCROLL_MS, KEY_TO_COMMAND_MS, KeyScroll, occurrenceCount, OccurrenceHighlight, OccurrenceNavigation, occurrenceStyle, segmentOccurrence, stepIndex } from './occurrences'
|
||||
import { clickAction, isCurrent, KEY_SCROLL_MS, KEY_TO_COMMAND_MS, KeyScroll, occurrenceCount, OccurrenceHighlight, OccurrenceNavigation, occurrenceStyle, segmentOccurrence, sourceOf, stepIndex } from './occurrences'
|
||||
|
||||
function name(text: string, offset: number): Segment {
|
||||
return { text, role: 'variable', offset }
|
||||
@@ -54,6 +54,16 @@ describe('occurrences:哪些段画高亮', () => {
|
||||
expect(segmentOccurrence(name('a', 0), [at(0, 1, 'read'), at(0, 1, 'write')])).toBe('strong')
|
||||
})
|
||||
|
||||
it('讲别处名字的段(refers,写在字符串里的参数名)按那个名字算:那个名字的出现盖住它就画、能是当前那一处,自己照抄的位置不算', () => {
|
||||
const param: Segment = { text: 'user_id', role: 'variable', offset: 40, refers: { startIndex: 100, endIndex: 107 } }
|
||||
expect(sourceOf(param)).toEqual({ start: 100, end: 107 })
|
||||
expect(segmentOccurrence(param, [at(100, 107, 'write')])).toBe('strong')
|
||||
expect(segmentOccurrence(param, [at(40, 47)])).toBeUndefined()
|
||||
expect(isCurrent(param, { name: 'user_id', occurrences: [at(100, 107)], current: 0 })).toBe(true)
|
||||
expect(sourceOf(name('x', 3))).toEqual({ start: 3, end: 4 })
|
||||
expect(sourceOf({ text: '常量', role: 'storage' })).toBeUndefined()
|
||||
})
|
||||
|
||||
it('真实的 Python 译文和属性表:定义处按写入、用到的地方按读取画;点分模块名每一节各按自己的范围认', async () => {
|
||||
const source = [
|
||||
'import luffy_agent.core.db',
|
||||
|
||||
@@ -8,7 +8,7 @@ export function occurrenceStyle(kind: Occurrence['kind']): OccurrenceStyle {
|
||||
}
|
||||
|
||||
/**
|
||||
* 一段文字画不画高亮、画哪种:它照抄自源码,在源码里占 [offset, offset + 字数),和哪处出现重叠就画,
|
||||
* 一段文字画不画高亮、画哪种:它讲的名字(sourceOf)和哪处出现重叠就画,
|
||||
* 同时碰上写入和读取的按写入画。没有下标的(译词、提示词、编辑状态的源码)不画。
|
||||
*/
|
||||
export function segmentOccurrence(segment: Segment, occurrences: readonly Occurrence[]): OccurrenceStyle | undefined {
|
||||
@@ -23,10 +23,20 @@ export function segmentOccurrence(segment: Segment, occurrences: readonly Occurr
|
||||
return style
|
||||
}
|
||||
|
||||
/** 段照抄自源码、在源码里占的 [offset, offset + 字数) 和这处出现重叠;没有下标的段不算。 */
|
||||
/**
|
||||
* 段讲的是源码里哪个名字,[start, end):讲别处名字的段(refers,写在字符串里的参数名)是那个名字,照抄自源码的段是它自己占的
|
||||
* [offset, offset + 字数);没有下标的段(译词、提示词)没有。跳到定义、单击高亮、各处出现画在哪都按它。
|
||||
*/
|
||||
export function sourceOf(segment: Segment): { start: number, end: number } | undefined {
|
||||
if (segment.refers)
|
||||
return { start: segment.refers.startIndex, end: segment.refers.endIndex }
|
||||
return segment.offset === undefined ? undefined : { start: segment.offset, end: segment.offset + segment.text.length }
|
||||
}
|
||||
|
||||
/** 段讲的名字(sourceOf)和这处出现重叠;没有下标的段不算。 */
|
||||
export function overlaps(segment: Segment, occurrence: Occurrence): boolean {
|
||||
const { offset } = segment
|
||||
return offset !== undefined && occurrence.start < offset + segment.text.length && offset < occurrence.end
|
||||
const source = sourceOf(segment)
|
||||
return source !== undefined && occurrence.start < source.end && source.start < occurrence.end
|
||||
}
|
||||
|
||||
/** 文字里(连框里)有段和这处出现重叠。 */
|
||||
|
||||
@@ -17,9 +17,10 @@ export type TokenRole
|
||||
/**
|
||||
* offset:照抄自源码里的名字、字符串时它在源码里的起始下标,⌘ / Ctrl 悬停、点击时拿它查定义;译词、提示词没有。
|
||||
* reference:库规则自己查定义的名字(Celery 的任务名)才有;webview 不看它,照样只报 offset,扩展端按 offset 认出来交给规则查。
|
||||
* color:这段自己的颜色(库规则按库自己的配色给的,例如 HTTP 方法),盖过词性的颜色,按主题挑暗色、亮色
|
||||
* color:这段自己的颜色(库规则按库自己的配色给的,例如 HTTP 方法),盖过词性的颜色,按主题挑暗色、亮色。
|
||||
* refers:这段讲的是源码里别处的一个名字(写在字符串里的名字讲的参数):跳到定义、高亮各处出现都当它是那个名字,见 sourceOf
|
||||
*/
|
||||
export interface Segment { text: string, role: TokenRole, offset?: number, reference?: RuleReference, color?: ThemeColor }
|
||||
export interface Segment { text: string, role: TokenRole, offset?: number, reference?: RuleReference, color?: ThemeColor, refers?: SourceRange }
|
||||
|
||||
/** 规则自己查得到定义的一个名字:哪个规则、规则自己认的键 */
|
||||
export interface RuleReference { rule: string, key: string }
|
||||
|
||||
Reference in new issue
Block a user