Skip to content

Commit

Permalink
Merge branch 'main' into label-annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCockx authored Jan 22, 2025
2 parents 36274ed + 41d996f commit 27cba81
Show file tree
Hide file tree
Showing 22 changed files with 1,429 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,40 @@
package com.regnosys.rosetta.ide

import com.regnosys.rosetta.generator.RosettaOutputConfigurationProvider
import org.eclipse.xtext.generator.IContextualOutputConfigurationProvider
import org.eclipse.xtext.documentation.IEObjectDocumentationProvider
import com.regnosys.rosetta.ide.contentassist.RosettaContentProposalProvider
import com.regnosys.rosetta.ide.contentassist.cancellable.CancellableContentAssistService
import com.regnosys.rosetta.ide.contentassist.cancellable.CancellableRosettaParser
import com.regnosys.rosetta.ide.contentassist.cancellable.ICancellableContentAssistParser
import com.regnosys.rosetta.ide.contentassist.cancellable.RosettaOperationCanceledManager
import com.regnosys.rosetta.ide.formatting.RosettaFormattingService
import com.regnosys.rosetta.ide.hover.RosettaDocumentationProvider
import com.regnosys.rosetta.ide.hover.RosettaHoverService
import com.regnosys.rosetta.ide.inlayhints.IInlayHintsResolver
import com.regnosys.rosetta.ide.inlayhints.RosettaInlayHintsService
import com.regnosys.rosetta.ide.inlayhints.IInlayHintsService
import com.regnosys.rosetta.ide.util.RangeUtils
import com.regnosys.rosetta.ide.semantictokens.ISemanticTokenTypesProvider
import com.regnosys.rosetta.ide.inlayhints.RosettaInlayHintsService
import com.regnosys.rosetta.ide.quickfix.ICodeActionProvider
import com.regnosys.rosetta.ide.quickfix.IResolveCodeActionService
import com.regnosys.rosetta.ide.quickfix.RosettaCodeActionProvider
import com.regnosys.rosetta.ide.quickfix.RosettaCodeActionService
import com.regnosys.rosetta.ide.quickfix.RosettaQuickFixProvider
import com.regnosys.rosetta.ide.quickfix.RosettaResolveCodeActionService
import com.regnosys.rosetta.ide.semantictokens.ISemanticTokenModifiersProvider
import com.regnosys.rosetta.ide.semantictokens.ISemanticTokenTypesProvider
import com.regnosys.rosetta.ide.semantictokens.ISemanticTokensService
import com.regnosys.rosetta.ide.semantictokens.RosettaSemanticTokensService
import com.regnosys.rosetta.ide.semantictokens.RosettaSemanticTokenModifiersProvider
import com.regnosys.rosetta.ide.semantictokens.RosettaSemanticTokenTypesProvider
import com.regnosys.rosetta.ide.semantictokens.RosettaSemanticTokensService
import com.regnosys.rosetta.ide.textmate.RosettaTextMateGrammarUtil
import org.eclipse.xtext.ide.server.formatting.FormattingService
import com.regnosys.rosetta.ide.formatting.RosettaFormattingService
import com.regnosys.rosetta.ide.util.RangeUtils
import org.eclipse.xtext.documentation.IEObjectDocumentationProvider
import org.eclipse.xtext.generator.IContextualOutputConfigurationProvider
import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalProvider
import org.eclipse.xtext.ide.editor.quickfix.IQuickFixProvider
import com.regnosys.rosetta.ide.quickfix.RosettaQuickFixProvider
import org.eclipse.xtext.ide.server.codeActions.ICodeActionService2
import com.regnosys.rosetta.ide.quickfix.RosettaQuickFixCodeActionService
import org.eclipse.xtext.ide.server.contentassist.ContentAssistService
import org.eclipse.xtext.service.OperationCanceledManager
import com.regnosys.rosetta.ide.contentassist.cancellable.ICancellableContentAssistParser
import com.regnosys.rosetta.ide.contentassist.cancellable.CancellableRosettaParser
import com.regnosys.rosetta.ide.contentassist.cancellable.CancellableContentAssistService
import com.regnosys.rosetta.ide.contentassist.cancellable.RosettaOperationCanceledManager
import com.regnosys.rosetta.ide.semantictokens.RosettaSemanticTokenModifiersProvider
import org.eclipse.xtext.ide.server.formatting.FormattingService
import org.eclipse.xtext.ide.server.hover.IHoverService
import com.regnosys.rosetta.ide.hover.RosettaHoverService
import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalProvider
import com.regnosys.rosetta.ide.contentassist.RosettaContentProposalProvider
import org.eclipse.xtext.service.OperationCanceledManager

/**
* Use this class to register ide components.
Expand Down Expand Up @@ -85,7 +89,15 @@ class RosettaIdeModule extends AbstractRosettaIdeModule {
}

def Class<? extends ICodeActionService2> bindICodeActionService2() {
RosettaQuickFixCodeActionService
RosettaCodeActionService
}

def Class<? extends IResolveCodeActionService> bindIResolveCodeActionService() {
RosettaResolveCodeActionService
}

def Class<? extends ICodeActionProvider> bindICodeActionProvider() {
RosettaCodeActionProvider
}

def Class<? extends ICancellableContentAssistParser> bindICancellableContentAssistParser() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.regnosys.rosetta.ide.quickfix;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.xtext.ide.server.ILanguageServerAccess;
import org.eclipse.xtext.ide.server.TextEditAcceptor;
import org.eclipse.xtext.ide.server.codeActions.ICodeActionService2.Options;

import com.regnosys.rosetta.rosetta.RosettaModel;

public abstract class AbstractCodeActionProvider implements ICodeActionProvider {

private static final Logger LOG = Logger.getLogger(RosettaCodeActionProvider.class);

@Override
public CodeAction resolve(CodeAction unresolved, Options options) {
String title = unresolved.getTitle();
if (unresolved == null || title == null) {
return null;
}

Method resolutionMethod = findResolutionMethod(getClass(), title);

if (resolutionMethod != null) {
try {
RosettaModel model = (RosettaModel) options.getResource().getContents().get(0);
List<TextEdit> edits = (List<TextEdit>) resolutionMethod.invoke(this, model);

ILanguageServerAccess languageServerAccess = options.getLanguageServerAccess();

WorkspaceEdit workspaceEdit = new WorkspaceEdit();
TextEditAcceptor editAcceptor = new TextEditAcceptor(workspaceEdit, languageServerAccess);
String uri = options.getResource().getURI().toString();

editAcceptor.accept(uri, options.getDocument(), edits);
unresolved.setEdit(workspaceEdit);
return unresolved;
} catch (Exception e) {
LOG.error("Error resolving code action: " + title, e);
}
}
return unresolved;
}

private Method findResolutionMethod(Class<? extends AbstractCodeActionProvider> clazz, String title) {
return Arrays.stream(clazz.getMethods()).filter(method -> {
CodeActionResolution annotation = method.getAnnotation(CodeActionResolution.class);
return annotation != null && annotation.value().equals(title);
}).findFirst().orElse(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.regnosys.rosetta.ide.quickfix;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface CodeActionResolution {
/**
* Specifies the title of the code action for which the annotated method provides a resolution.
*
* @return the title of the associated code action.
*/
String value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.regnosys.rosetta.ide.quickfix;

import java.util.List;

import org.eclipse.lsp4j.CodeAction;
import org.eclipse.xtext.ide.server.codeActions.ICodeActionService2.Options;

public interface ICodeActionProvider {
List<CodeAction> getCodeActions(Options options);

CodeAction resolve(CodeAction unresolved, Options options);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.regnosys.rosetta.ide.quickfix;

import org.eclipse.lsp4j.CodeAction;
import org.eclipse.xtext.ide.server.codeActions.ICodeActionService2.Options;

public interface IResolveCodeActionService {
CodeAction getCodeActionResolution(CodeAction unresolved, Options baseOptions);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.regnosys.rosetta.ide.quickfix;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import org.eclipse.emf.common.util.EList;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.xtext.ide.server.codeActions.ICodeActionService2.Options;

import com.regnosys.rosetta.ide.util.CodeActionUtils;
import com.regnosys.rosetta.rosetta.Import;
import com.regnosys.rosetta.rosetta.RosettaModel;
import com.regnosys.rosetta.utils.ImportManagementService;

public class RosettaCodeActionProvider extends AbstractCodeActionProvider {
@Inject
private ImportManagementService importManagementService;
@Inject
private CodeActionUtils codeActionUtils;

@Override
public List<CodeAction> getCodeActions(Options options) {
List<CodeAction> result = new ArrayList<>();

// Handle Sorting CodeAction
RosettaModel model = (RosettaModel) options.getResource().getContents().get(0);
if (!importManagementService.isSorted(model.getImports())) {
result.add(codeActionUtils.createUnresolvedCodeAction("Sort imports", options.getCodeActionParams(),
CodeActionKind.SourceOrganizeImports));
}

return result;
}

@CodeActionResolution("Sort imports")
public List<TextEdit> sortImports(RosettaModel model) {
EList<Import> imports = model.getImports();

Range importsRange = codeActionUtils.getImportsRange(imports);

importManagementService.sortImports(imports);
String sortedImportsText = importManagementService.toString(imports);

return List.of(new TextEdit(importsRange, sortedImportsText));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2024 REGnosys
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.regnosys.rosetta.ide.quickfix;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import javax.inject.Inject;

import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.xtext.ide.editor.quickfix.DiagnosticResolution;
import org.eclipse.xtext.ide.editor.quickfix.IQuickFixProvider;
import org.eclipse.xtext.ide.server.codeActions.ICodeActionService2;

import com.regnosys.rosetta.ide.util.CodeActionUtils;

public class RosettaCodeActionService implements ICodeActionService2 {

@Inject
private IQuickFixProvider quickfixes;
@Inject
private CodeActionUtils codeActionUtils;
@Inject
private ICodeActionProvider codeActionProvider;

@Override
public List<Either<Command, CodeAction>> getCodeActions(Options options) {
List<Either<Command, CodeAction>> result = new ArrayList<>();

//Handle Code Actions
List<Either<Command, CodeAction>> codeActions = codeActionProvider.getCodeActions(options).stream()
.map(action -> Either.<Command, CodeAction>forRight(action))
.collect(Collectors.toList());
result.addAll(codeActions);

boolean handleQuickfixes = options.getCodeActionParams().getContext().getOnly() == null
|| options.getCodeActionParams().getContext().getOnly().isEmpty()
|| options.getCodeActionParams().getContext().getOnly().contains(CodeActionKind.QuickFix);

if (handleQuickfixes) {
List<Diagnostic> diagnostics = options.getCodeActionParams().getContext().getDiagnostics();

for (Diagnostic diagnostic : diagnostics) {
Options diagnosticOptions = codeActionUtils.createOptionsForSingleDiagnostic(options, diagnostic);
List<DiagnosticResolution> resolutions = quickfixes.getResolutions(diagnosticOptions, diagnostic)
.stream().sorted(Comparator.nullsLast(Comparator.comparing(DiagnosticResolution::getLabel)))
.collect(Collectors.toList());
for (DiagnosticResolution resolution : resolutions) {
result.add(Either
.forRight(codeActionUtils.createUnresolvedFix(resolution.getLabel(), options.getCodeActionParams(), diagnostic)));
}
}
}

return result;
}

}
Loading

0 comments on commit 27cba81

Please sign in to comment.