Skip to content

Commit

Permalink
feat: improve the accuracy of queries via __source
Browse files Browse the repository at this point in the history
  • Loading branch information
zjxxxxxxxxx committed Sep 19, 2023
1 parent d136f44 commit 1c39c8e
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 98 deletions.
5 changes: 5 additions & 0 deletions .changeset/yellow-wasps-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@open-editor/client': patch
---

improve the accuracy of queries via \_\_source
109 changes: 60 additions & 49 deletions packages/client/src/resolve/framework/vue2.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { getComponentNameByFile, isValidFileName } from '../util';
import { isStr } from '@open-editor/shared';

import {
getVueComponentName,
hasVueSource,
isValidFileName,
parseVueSource,
} from '../util';
import { ResolveDebug } from '../resolveDebug';
import { ElementSourceMeta } from '../resolveSource';
import { parse__source } from './vue3';

export function resolveVue2(
debug: ResolveDebug,
Expand All @@ -12,63 +18,38 @@ export function resolveVue2(
debug.value = debug.value._vnode.componentInstance;
}

const source = find__source(debug);
if (source) {
return resolveSourceFrom__source({ source, ...debug }, tree, deep);
if (hasVueSource(debug.element)) {
return resolveSourceFromVueSource(debug, tree, deep);
}
return resolveSourceFromInstance(debug.value, tree, deep);
}

function resolveSourceFrom__source(
debug: ResolveDebug & {
source: ReturnType<typeof parse__source>;
},
function resolveSourceFromVueSource(
debug: ResolveDebug,
tree: Partial<ElementSourceMeta>[],
deep?: boolean,
) {
let instance = debug.value;
let source = debug.source;
console.log(source);
while (instance) {
if (instance.$parent == null) {
let [instance, source] = resolveVueSourceStart(debug);

while (instance && instance.$vnode) {
if (instance.$parent.$vnode == null) {
tree.push({
name: getComponentName(instance),
...source,
});
return;
} else if (get__source(instance)) {
const instanceSource = parse__source(get__source(instance));
if (
source.file !== instanceSource.file &&
isValidFileName(instanceSource.file)
) {
} else if (getVueSource(instance)) {
const __source = parseVueSource(getVueSource(instance));
if (isValidFileName(__source.file)) {
tree.push({
name: getComponentName(instance),
...source,
});
if (!deep) return;

source = instanceSource;
source = __source;
}
}
instance = instance.$parent;
}
}

function find__source(debug: ResolveDebug) {
let element = debug.originalElement;
while (element && !element.getAttribute('__source')) {
element = element.parentElement!;
}
if (element?.getAttribute('__source')) {
return parse__source(element.getAttribute('__source')!);
}

let instance = debug.value;
while (instance) {
if (get__source(instance)) {
return parse__source(get__source(instance));
}
instance = instance.$parent;
}
}
Expand All @@ -79,12 +60,11 @@ function resolveSourceFromInstance(
deep?: boolean,
) {
while (instance && instance.$vnode) {
const { Ctor } = instance.$vnode.componentOptions;
const __file = Ctor?.__file ?? Ctor.options?.__file;
if (isValidFileName(__file)) {
const file = getComponentFile(instance);
if (isValidFileName(file)) {
tree.push({
name: getComponentName(Ctor),
file: __file,
name: getComponentName(instance),
file,
});

if (!deep) return;
Expand All @@ -94,11 +74,42 @@ function resolveSourceFromInstance(
}
}

function get__source(instance: any) {
return instance.componentInstance?.$props?.__source;
function resolveVueSourceStart(debug: ResolveDebug) {
let instance = debug.value;
let element = debug.originalElement;

while (element && !element.getAttribute('__source')) {
element = element.parentElement!;
}

const __source = element.getAttribute('__source');
if (isStr(__source)) {
return <const>[instance, parseVueSource(__source)];
}

while (instance) {
const __source = getVueSource(instance);
if (isStr(__source)) {
return <const>[instance, parseVueSource(__source)];
}

instance = instance.$parent;
}

return [];
}

function getVueSource(instance: any) {
return instance.$vnode.componentInstance?.$props?.__source;
}

function getComponentName(instance: any) {
const { Ctor } = instance.$vnode.componentOptions;
const file = getComponentFile(instance);
return Ctor.options?.name ?? getVueComponentName(file);
}

function getComponentName(Ctor: any) {
const __file = Ctor?.__file ?? Ctor.options?.__file;
return Ctor.options?.name ?? getComponentNameByFile(__file, 'vue');
function getComponentFile(instance: any) {
const { Ctor } = instance.$vnode.componentOptions;
return Ctor?.__file ?? Ctor.options?.__file;
}
87 changes: 44 additions & 43 deletions packages/client/src/resolve/framework/vue3.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { ComponentInternalInstance } from '@vue/runtime-core';
import type { ComponentInternalInstance } from '@vue/runtime-core';
import { isStr } from '@open-editor/shared';

import { getComponentNameByFile, isValidFileName } from '../util';
import {
getVueComponentName,
hasVueSource,
isValidFileName,
parseVueSource,
} from '../util';
import { ResolveDebug } from '../resolveDebug';
import { ElementSourceMeta } from '../resolveSource';

Expand All @@ -9,73 +15,42 @@ export function resolveVue3(
tree: Partial<ElementSourceMeta>[],
deep?: boolean,
) {
const source = find__source(debug);
if (source) {
return resolveSourceFrom__source({ source, ...debug }, tree, deep);
if (hasVueSource(debug.element)) {
return resolveSourceFromVueSource(debug, tree, deep);
}
return resolveSourceFromInstance(debug.value, tree, deep);
}

function resolveSourceFrom__source(
debug: ResolveDebug<ComponentInternalInstance> & {
source: ReturnType<typeof parse__source>;
},
function resolveSourceFromVueSource(
debug: ResolveDebug<ComponentInternalInstance>,
tree: Partial<ElementSourceMeta>[],
deep?: boolean,
) {
let instance = debug.value;
let source = debug.source;
let [instance, source] = resolveVueSourceStart(debug);

while (instance) {
if (instance.parent == null) {
tree.push({
name: getComponentName(instance),
...source,
});
return;
} else if (instance.props.__source) {
const instanceSource = parse__source(instance.props.__source as string);
if (
source.file !== instanceSource.file &&
isValidFileName(instanceSource.file)
) {
const __source = parseVueSource(instance.props.__source as string);
if (isValidFileName(__source.file)) {
tree.push({
name: getComponentName(instance),
...source,
});
if (!deep) return;

source = instanceSource;
source = __source;
}
}
instance = instance.parent;
}
}

function find__source(debug: ResolveDebug<ComponentInternalInstance>) {
let instance = debug.value;

const __source = debug.element.getAttribute('__source');
if (__source) {
return parse__source(__source);
}

while (instance) {
if (instance.props.__source) {
return parse__source(instance.props.__source as string);
}
instance = instance.parent;
}
}

export function parse__source(__source: string) {
const [file, line, column] = __source.split(':');
return {
file,
line: Number(line),
column: Number(column),
};
}

function resolveSourceFromInstance(
instance: ComponentInternalInstance | null | undefined,
tree: Partial<ElementSourceMeta>[],
Expand All @@ -89,14 +64,40 @@ function resolveSourceFromInstance(
});
if (!deep) return;
}

instance = instance.parent;
}
}

function resolveVueSourceStart(debug: ResolveDebug<ComponentInternalInstance>) {
let instance = debug.value;
let element = debug.element;

while (element && !element.getAttribute('__source')) {
element = element.parentElement!;
}

const __source = element.getAttribute('__source');
if (isStr(__source)) {
return <const>[instance, parseVueSource(__source)];
}

while (instance) {
const __source = instance.props.__source;
if (isStr(__source)) {
return <const>[instance.parent, parseVueSource(__source)];
}

instance = instance.parent;
}

return [];
}

function getComponentName(instance: ComponentInternalInstance) {
return (
instance.type.name ??
instance.type.__name ??
getComponentNameByFile(instance.type.__file, 'vue')
getVueComponentName(instance.type.__file)
);
}
2 changes: 1 addition & 1 deletion packages/client/src/resolve/resolveSource.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { resolveDebug } from './resolveDebug';
import { ensureFileName } from './util';
import { resolveDebug } from './resolveDebug';
import { resolveReact18 } from './framework/react18';
import { resolveReact15 } from './framework/react15';
import { resolveVue3 } from './framework/vue3';
Expand Down
34 changes: 29 additions & 5 deletions packages/client/src/resolve/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ export function ensureFileName(fileName: string) {
return `/${fileName.replace(/^\//, '')}`;
}

export function getComponentNameByFile(file = '', suffix = '') {
if (file.endsWith(`.${suffix}`)) {
const matchRE = new RegExp(`([^/.]+).${suffix}$`);
return file.match(matchRE)?.[1];
}
const vueComponentNameRE = /([^/.]+)\.vue$/;
export function getVueComponentName(file = '') {
return file.match(vueComponentNameRE)?.[1];
}

export function isValidFileName(fileName?: string) {
Expand All @@ -25,3 +23,29 @@ export function isValidFileName(fileName?: string) {
}
return false;
}

let hvs: boolean | null = null;
export function hasVueSource(element: HTMLElement) {
if (hvs != null) {
return hvs;
}

while (element) {
if (element.getAttribute('__source') != null) {
return (hvs = true);
}

element = element.parentElement!;
}

return (hvs = false);
}

export function parseVueSource(__source: string) {
const [file, line, column] = __source.split(':');
return {
file,
line: Number(line),
column: Number(column),
};
}

0 comments on commit 1c39c8e

Please sign in to comment.