Skip to content
Merged
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
38 changes: 25 additions & 13 deletions ui/src/components/codemirror-editor/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import { python } from '@codemirror/lang-python'
import { oneDark } from '@codemirror/theme-one-dark'
import { linter, type Diagnostic } from '@codemirror/lint'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
import debounce from 'lodash/debounce'
import { throttle } from 'lodash'

defineOptions({ name: 'CodemirrorEditor' })

Expand Down Expand Up @@ -79,22 +79,34 @@ const data = computed({

function getRangeFromLineAndColumn(state: any, line: number, column: number, end_column?: number) {
const l = state.doc.line(line)
const form = l.from + column
const to_end_column = l.from + end_column
const lineLength = l.length
const safeColumn = Math.max(0, Math.min(column, lineLength))
const fromPos = l.from + safeColumn
let safeEndColumn
if (end_column !== undefined) {
safeEndColumn = Math.max(0, Math.min(end_column, lineLength))
} else {
safeEndColumn = lineLength
}
const toPos = l.from + safeEndColumn
const finalFrom = Math.min(fromPos, toPos)
const finalTo = Math.max(fromPos, toPos)
return {
form: form > l.to ? l.to : form,
to: end_column && to_end_column < l.to ? to_end_column : l.to,
from: finalFrom,
to: finalTo,
}
}

const asyncLint = debounce(async (doc: string) => {
const res = await loadSharedApi({ type: 'tool', systemType: apiType.value }).postPylint(doc)
const asyncLint = throttle(async (view: any) => {
const res = await loadSharedApi({ type: 'tool', systemType: apiType.value }).postPylint(
view.state.doc.toString(),
)
return res.data
}, 500)

const regexpLinter = linter(async (view) => {
const currentstate = view.state
const diagnostics: Diagnostic[] = []
const lintResults = await asyncLint(view.state.doc.toString())
const lintResults = await asyncLint(view)
if (!lintResults || lintResults.length === 0) {
return diagnostics
}
Expand All @@ -105,15 +117,15 @@ const regexpLinter = linter(async (view) => {
limitedResults.forEach((element: any) => {
try {
const range = getRangeFromLineAndColumn(
view.state,
currentstate,
element.line,
element.column,
element.endColumn,
)
// 验证范围有效性
if (range.form >= 0 && range.to >= range.form) {
if (range.from >= 0 && range.to >= range.from) {
diagnostics.push({
from: range.form,
from: range.from,
to: range.to,
severity: element.type === 'error' ? 'error' : 'warning',
message: element.message,
Expand All @@ -125,7 +137,7 @@ const regexpLinter = linter(async (view) => {
})
return diagnostics
})
const extensions = [python(), regexpLinter, oneDark]
const extensions = [python(), oneDark, regexpLinter]
const codemirrorStyle = {
height: '210px!important',
width: '100%',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple of potential optimizations and corrections in the code:

  1. Consistent Throttle vs Debounce:

    • The asyncLint function is currently using debounce, but it should be set to throttle. This ensures that the API call does not happen more frequently than every 500 milliseconds.
  2. Potential Off-by-One Error:

    • In the getRangeFromLineAndColumn function, there's logic to calculate the range positions considering end columns. However, this might lead to off-by-one errors if column or end_column are invalid indices. You might want to add checks for these cases early.
  3. Variable Names:

    • There are some variable names that could be clearer or improved. For example, safeColumn and finalTo could be renamed for better readability.
  4. Code Formatting:

    • Ensure consistent indentation and spacing throughout the file for better readability.

Here's the corrected version of the code with these suggestions applied:

// ... other imports ...

function getRangeFromLineAndColumn(state: any, line: number, column: number, end_column?: number) {
  const l = state.doc.line(line);
  const safeColumn = Math.max(0, Math.min(column, l.length));
  const fromPos = l.from + safeColumn;
  
  let safeEndColumn;
  if (end_column !== undefined) {
    safeEndColumn = Math.max(0, Math.min(end_column, l.length));
  } else {
    safeEndColumn = l.length;
  }

  const toPos = l.from + safeEndColumn;

  return {
    from: Math.min(fromPos, toPos),
    to: Math.max(fromPos, toPos),
  };
}

const asyncLintThrottled = throttle(async (view: any) => {
  const res = await loadSharedApi({ type: 'tool', systemType: apiType.value }).postPylint(view.state.doc.toString());
  return res.data;
}, 500);

const regexpLinter = linter(async (view) => {
  const currentstate = view.state;
  const diagnostics: Diagnostic[] = [];
  const lintResults = await asyncLintThrottled(view); // Use the throttled function for consistency

  if (!lintResults || lintResults.length === 0) {
    return diagnostics; // Return diagnostics only if they are available
  }

  const limitedResults = lintResults.filter((result) => result.severity === 'info' || result.severity === 'warning'); // Limit results based on severity

  limitedResults.forEach((element: any) => {
    try {
      const range = getRangeFromLineAndColumn(currentstate, element.line, element.column, element.endColumn);
      
      // Add validation here if necessary...
      if (range.from >= 0 && range.to >= range.from){
        diagnostics.push({
          from: range.from,
          to: range.to,
          severity: element.type === 'error' ? 'error' : 'warning',
          message: element.message,
        });
      }
    } catch {};
  });

  return diagnostics;
});

const extensions = [
  python(),
  onesDark,
  regexpLinter
];

const codemirrorStyle = {
  height: "210px!important",
  width: "100%"
};

These changes ensure that the code functions correctly and improves its maintainability by being clear about intent and handling edge cases appropriately.

Expand Down
Loading