Skip to content

Commit

Permalink
PR Feedback
Browse files Browse the repository at this point in the history
- Improve handling of auto-completion to allow partial match
- Avoid opening error markers in mapping diagram
  • Loading branch information
martin-fleck-at committed May 27, 2024
1 parent 4174776 commit 83e9f60
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ import { v4 as uuid } from 'uuid';
import { CompletionItemKind, InsertTextFormat, TextEdit } from 'vscode-languageserver-protocol';
import type { Range } from 'vscode-languageserver-types';
import { CrossModelServices } from './cross-model-module.js';
import { RelationshipAttribute, isAttributeMapping, isReferenceSource } from './generated/ast.js';
import { AttributeMapping, RelationshipAttribute, isAttributeMapping, isReferenceSource } from './generated/ast.js';
import { fixDocument } from './util/ast-util.js';
import { isExpressionStart } from '@crossbreeze/protocol';

/**
* Custom completion provider that only shows the short options to the user if a longer, fully-qualified version is also available.
Expand All @@ -28,7 +27,7 @@ export class CrossModelCompletionProvider extends DefaultCompletionProvider {
protected packageId?: string;

readonly completionOptions = {
triggerCharacters: ['\n', ' ']
triggerCharacters: ['\n', ' ', '{']
};

constructor(
Expand Down Expand Up @@ -74,18 +73,7 @@ export class CrossModelCompletionProvider extends DefaultCompletionProvider {
return this.completionForId(context, assignment, acceptor);
}
if (isAttributeMapping(context.node) && assignment.feature === 'expression') {
const node = context.node;
const text = context.textDocument.getText();
const existingText = text.substring(context.tokenOffset, context.offset);
if (isExpressionStart(existingText)) {
node.sources.filter(isReferenceSource).forEach(source => {
acceptor(context, {
label: source.value.$refText,
textEdit: TextEdit.insert(context.textDocument.positionAt(context.offset), source.value.$refText)
});
});
return;
}
return this.completeAttributeMappingExpression(context, context.node, acceptor);
}
if (GrammarAST.isRuleCall(assignment.terminal) && assignment.terminal.rule.ref) {
const type = this.getRuleType(assignment.terminal.rule.ref);
Expand All @@ -100,6 +88,33 @@ export class CrossModelCompletionProvider extends DefaultCompletionProvider {
}
}

protected completeAttributeMappingExpression(
context: CompletionContext,
mapping: AttributeMapping,
acceptor: CompletionAcceptor
): MaybePromise<void> {
const text = context.textDocument.getText();
const expressionUpToCursor = text.substring(context.tokenOffset, context.offset);
const referenceStart = expressionUpToCursor.lastIndexOf('{{');
const referenceEnd = expressionUpToCursor.lastIndexOf('}}');
if (referenceEnd >= referenceStart) {
// we are not within a reference part
return;
}
const start = context.textDocument.positionAt(context.tokenOffset + referenceStart + '{{'.length);
const end = context.textDocument.positionAt(context.offset);
const reference = context.textDocument.getText({ start, end }).trim();
mapping.sources
.filter(isReferenceSource)
.filter(source => reference.length === 0 || source.value.$refText.startsWith(reference))
.forEach(source => {
acceptor(context, {
label: source.value.$refText,
textEdit: TextEdit.replace({ start, end }, source.value.$refText)
});
});
}

protected getRuleType(rule: GrammarAST.AbstractRule): string | undefined {
if (GrammarAST.isTerminalRule(rule)) {
return rule.type?.name ?? 'string';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@
* Copyright (c) 2023 CrossBreeze.
********************************************************************************/

import { ContainerContext, DiagramConfiguration, GLSPDiagramWidget, GLSPTheiaFrontendModule } from '@eclipse-glsp/theia-integration';
import {
ContainerContext,
DiagramConfiguration,
GLSPDiagramWidget,
GLSPTheiaFrontendModule,
registerDiagramManager
} from '@eclipse-glsp/theia-integration';

import { MappingDiagramLanguage } from '../../common/crossmodel-diagram-language';
import { MappingDiagramConfiguration } from './mapping-diagram-configuration';
import { MappingDiagramManager } from './mapping-diagram-manager';
import { MappingDiagramWidget } from './mapping-diagram-widget';

export class MappingDiagramModule extends GLSPTheiaFrontendModule {
Expand All @@ -27,6 +34,11 @@ export class MappingDiagramModule extends GLSPTheiaFrontendModule {
super.bindDiagramWidgetFactory(context);
context.rebind(GLSPDiagramWidget).to(MappingDiagramWidget);
}

override configureDiagramManager(context: ContainerContext): void {
context.bind(MappingDiagramManager).toSelf().inSingletonScope();
registerDiagramManager(context.bind, MappingDiagramManager, false);
}
}

export default new MappingDiagramModule();
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/********************************************************************************
* Copyright (c) 2024 CrossBreeze.
********************************************************************************/

import { GLSPDiagramManager } from '@eclipse-glsp/theia-integration';
import { URI } from '@theia/core';
import { WidgetOpenerOptions } from '@theia/core/lib/browser';
import { injectable } from '@theia/core/shared/inversify';
import { MappingDiagramLanguage } from '../../common/crossmodel-diagram-language';
import { codiconCSSString } from '@eclipse-glsp/client';

export interface ProblemMarkerOpenerOptions extends WidgetOpenerOptions {
selection?: Range;
}

@injectable()
export class MappingDiagramManager extends GLSPDiagramManager {
get label(): string {
return MappingDiagramLanguage.label;
}

override get iconClass(): string {
return MappingDiagramLanguage.iconClass ?? codiconCSSString('type-hierarchy-sub');
}

override get fileExtensions(): string[] {
return MappingDiagramLanguage.fileExtensions;
}

override get diagramType(): string {
return MappingDiagramLanguage.diagramType;
}

override get contributionId(): string {
return MappingDiagramLanguage.contributionId;
}

override canHandle(uri: URI, options?: ProblemMarkerOpenerOptions | undefined): number {
if (options?.selection) {
return 0;
}
return super.canHandle(uri, options);
}
}

0 comments on commit 83e9f60

Please sign in to comment.