Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate the client's file formatting options with JDT code action handlers #1657

Merged
merged 2 commits into from
Feb 24, 2021
Merged
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions launch/jdt.ls.socket-stream.launch
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
<setEntry value="ch.qos.logback.classic@default:default"/>
<setEntry value="ch.qos.logback.core@default:default"/>
<setEntry value="ch.qos.logback.slf4j@default:default"/>
<setEntry value="com.google.gson*2.8.2.v20180104-1110@default:default"/>
<setEntry value="com.google.gson@default:default"/>
<setEntry value="com.google.guava@default:default"/>
<setEntry value="javax.inject@default:default"/>
<setEntry value="javax.xml@default:default"/>
<setEntry value="org.apache.ant@default:default"/>
<setEntry value="org.apache.commons.io*2.6.0.v20190123-2029@default:default"/>
<setEntry value="org.apache.commons.io@default:default"/>
<setEntry value="org.apache.commons.lang3@default:default"/>
<setEntry value="org.apache.felix.scr@1:true"/>
<setEntry value="org.apache.log4j@default:default"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2018 Red Hat Inc. and others.
* Copyright (c) 2016-2020 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
Expand All @@ -24,6 +24,7 @@
import org.eclipse.lsp4j.ApplyWorkspaceEditParams;
import org.eclipse.lsp4j.ApplyWorkspaceEditResponse;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.ConfigurationParams;
import org.eclipse.lsp4j.ExecuteCommandParams;
import org.eclipse.lsp4j.MessageActionItem;
import org.eclipse.lsp4j.MessageParams;
Expand Down Expand Up @@ -222,6 +223,13 @@ public void semanticHighlighting(SemanticHighlightingParams params) {
client.semanticHighlighting(params);
}

/**
* @see {@link LanguageClient#configuration(ConfigurationParams)}
*/
public List<Object> configuration(ConfigurationParams configurationParams) {
return this.client.configuration(configurationParams).join();
}

public void disconnect() {
if (logHandler != null) {
logHandler.uninstall();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

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

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
Expand Down Expand Up @@ -158,7 +159,8 @@ private void insertMethod(IField field, ListRewrite rewrite, AccessorKind kind)
stub = GetterSetterUtil.getSetterStub(field, name, generateComments, flags);
}

String formattedStub = CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, stub, 0, delimiter, type.getJavaProject().getOptions(true));
Map<String, String> options = type.getCompilationUnit() != null ? type.getCompilationUnit().getOptions(true) : type.getJavaProject().getOptions(true);
String formattedStub = CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, stub, 0, delimiter, options);
MethodDeclaration declaration = (MethodDeclaration) rewrite.getASTRewrite().createStringPlaceholder(formattedStub, ASTNode.METHOD_DECLARATION);
rewrite.insertLast(declaration, null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,8 @@ public String updateReplacementString(IDocument document, int offset, ImportRewr
buf.append(newBody);
// use the code formatter
String lineDelim = TextUtilities.getDefaultLineDelimiter(document);
final IJavaProject project = fCompilationUnit.getJavaProject();
IRegion lineInfo = document.getLineInformationOfOffset(fReplacementOffset);
Map<String, String> options = project != null ? project.getOptions(true) : JavaCore.getOptions();
Map<String, String> options = fCompilationUnit.getOptions(true);
String replacementString = CodeFormatterUtil.format(CodeFormatter.K_EXPRESSION, buf.toString(), 0, lineDelim, options);
int lineEndOffset = lineInfo.getOffset() + lineInfo.getLength();
int p = offset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public String updateReplacementString(IDocument document, int offset, ImportRewr

ITrackedNodePosition position= rewrite.track(stub);
try {
Map<String, String> options = fJavaProject.getOptions(true);
Map<String, String> options = fCompilationUnit.getOptions(true);

rewrite.rewriteAST(recoveredDocument, options).apply(recoveredDocument);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ public Change createChange(IProgressMonitor pm) throws CoreException {
result.addTextEditGroup(new TextEditGroup(RefactoringCoreMessages.ExtractMethodRefactoring_organize_imports, new TextEdit[] { edit }));
}
try {
Map formatter = this.fFormatterOptions == null ? fCUnit.getJavaProject().getOptions(true) : this.fFormatterOptions;
Map formatter = this.fFormatterOptions == null ? fCUnit.getOptions(true) : this.fFormatterOptions;
IDocument document = new Document(fCUnit.getSource());
root.addChild(fRewriter.rewriteAST(document, formatter));
} catch (JavaModelException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ private void createJavadoc() throws JavaModelException {
public void createEdit() throws JavaModelException {
try {
IDocument document= new Document(fDelegateRewrite.getCu().getBuffer().getContents());
TextEdit edit= fDelegateRewrite.getASTRewrite().rewriteAST(document, fDelegateRewrite.getCu().getJavaProject().getOptions(true));
TextEdit edit= fDelegateRewrite.getASTRewrite().rewriteAST(document, fDelegateRewrite.getCu().getOptions(true));
edit.apply(document, TextEdit.UPDATE_REGIONS);

int tabWidth = CodeFormatterUtil.getTabWidth(fOriginalRewrite.getCu().getJavaProject());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ private static Change createDeleteChange(ICompilationUnit cu, List<IJavaElement>
private static TextChange addTextEditFromRewrite(TextChangeManager manager, ICompilationUnit cu, ASTRewrite rewrite) throws CoreException {
try {
ITextFileBuffer buffer= RefactoringFileBuffers.acquire(cu);
TextEdit resultingEdits= rewrite.rewriteAST(buffer.getDocument(), cu.getJavaProject().getOptions(true));
TextEdit resultingEdits= rewrite.rewriteAST(buffer.getDocument(), cu.getOptions(true));
TextChange textChange= manager.get(cu);
if (textChange instanceof TextFileChange) {
TextFileChange tfc= (TextFileChange) textChange;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private MethodDeclaration getStub(ASTRewrite rewrite, ASTNode targetTypeDecl) th
if (!isAbstractMethod && !isVoid) {
ReturnStatement returnStatement= ast.newReturnStatement();
returnStatement.setExpression(ASTNodeFactory.newDefaultExpression(ast, returnType, 0));
bodyStatement= ASTNodes.asFormattedString(returnStatement, 0, String.valueOf('\n'), getCompilationUnit().getJavaProject().getOptions(true));
bodyStatement= ASTNodes.asFormattedString(returnStatement, 0, String.valueOf('\n'), getCompilationUnit().getOptions(true));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private MethodDeclaration createNewMethodDeclaration(AST ast, IMethodBinding bin
}
}

String bodyStatement = (invocation == null) ? "" : ASTNodes.asFormattedString(invocation, 0, String.valueOf('\n'), getCompilationUnit().getJavaProject().getOptions(true)); //$NON-NLS-1$
String bodyStatement = (invocation == null) ? "" : ASTNodes.asFormattedString(invocation, 0, String.valueOf('\n'), getCompilationUnit().getOptions(true)); //$NON-NLS-1$
String placeHolder= CodeGeneration.getMethodBodyContent(getCompilationUnit(), name, name, true, bodyStatement, String.valueOf('\n'));
if (placeHolder != null) {
ASTNode todoNode= rewrite.createStringPlaceholder(placeHolder, ASTNode.RETURN_STATEMENT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ protected ASTRewrite getRewrite() throws CoreException {
if (expression != null) {
ReturnStatement returnStatement = ast.newReturnStatement();
returnStatement.setExpression(expression);
bodyStatement = ASTNodes.asFormattedString(returnStatement, 0, delimiter, unit.getJavaProject().getOptions(true));
bodyStatement = ASTNodes.asFormattedString(returnStatement, 0, delimiter, unit.getOptions(true));
}
}
String placeHolder = CodeGeneration.getMethodBodyContent(unit, methodBinding.getDeclaringClass().getName(), methodBinding.getName(), false, bodyStatement, delimiter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

Expand All @@ -26,7 +28,9 @@
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.internal.ui.text.correction.IProblemLocationCore;
import org.eclipse.jdt.internal.ui.text.correction.ProblemLocationCore;
Expand All @@ -40,6 +44,7 @@
import org.eclipse.jdt.ls.core.internal.corrections.RefactorProcessor;
import org.eclipse.jdt.ls.core.internal.corrections.proposals.ChangeCorrectionProposal;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences;
import org.eclipse.jdt.ls.core.internal.text.correction.AssignToVariableAssistCommandProposal;
import org.eclipse.jdt.ls.core.internal.text.correction.CUCorrectionCommandProposal;
import org.eclipse.jdt.ls.core.internal.text.correction.NonProjectFixProcessor;
Expand Down Expand Up @@ -86,6 +91,32 @@ public List<Either<Command, CodeAction>> getCodeActionCommands(CodeActionParams
return Collections.emptyList();
}

Map<String, Object> formattingOptions = ConfigurationHandler.getFormattingOptions(params.getTextDocument().getUri());
if (formattingOptions != null && !formattingOptions.isEmpty()) {
Object tabSizeValue = formattingOptions.get(Preferences.JAVA_CONFIGURATION_TABSIZE);
Object insertSpacesValue = formattingOptions.get(Preferences.JAVA_CONFIGURATION_INSERTSPACES);
Map<String, String> customOptions = new HashMap<>();
if (tabSizeValue != null) {
try {
int tabSize = Integer.parseInt(String.valueOf(tabSizeValue));
if (tabSize > 0) {
customOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, Integer.toString(tabSize));
}
} catch (Exception ex) {
// do nothing
}
}

if (insertSpacesValue != null) {
boolean insertSpaces = Boolean.parseBoolean(String.valueOf(insertSpacesValue));
customOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, insertSpaces ? JavaCore.SPACE : JavaCore.TAB);
}

if (!customOptions.isEmpty()) {
unit.setOptions(customOptions);
}
}

CompilationUnit astRoot = getASTRoot(unit, monitor);
if (astRoot == null || monitor.isCanceled()) {
return Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*******************************************************************************
* Copyright (c) 2020 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal.handlers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.preferences.Preferences;
import org.eclipse.lsp4j.ConfigurationItem;
import org.eclipse.lsp4j.ConfigurationParams;

public class ConfigurationHandler {

private ConfigurationHandler() {}

/**
* Query the format setting (insertSpace and tabSize) for the given uri.
* Will return {@code null} if the 'workspace/configuration' request is not supported,
* @param uri The target uri to query
* @return a map stores the setting keys and their values, for any setting key which is not
* available at the client side, a {@code null} value will be provided.
*/
public static Map<String, Object> getFormattingOptions(String uri) {
if (!JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isWorkspaceConfigurationSupported()) {
return null;
};

List<ConfigurationItem> configurationItems = new ArrayList<>();
String[] settingKeys = {
Preferences.JAVA_CONFIGURATION_TABSIZE,
Preferences.JAVA_CONFIGURATION_INSERTSPACES
};

ConfigurationItem tabSizeItem = new ConfigurationItem();
tabSizeItem.setScopeUri(uri);
tabSizeItem.setSection(settingKeys[0]);
configurationItems.add(tabSizeItem);

ConfigurationItem insertSpacesItem = new ConfigurationItem();
insertSpacesItem.setScopeUri(uri);
insertSpacesItem.setSection(settingKeys[1]);
configurationItems.add(insertSpacesItem);

ConfigurationParams configurationParams = new ConfigurationParams(configurationItems);
List<Object> response = JavaLanguageServerPlugin.getInstance().getClientConnection().configuration(configurationParams);

Map<String, Object> results = new HashMap<>();
int minLength = Math.min(settingKeys.length, response.size());
for (int i = 0; i < minLength; i++) {
results.put(settingKeys[i], response.get(i));
}
return results;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private IRegion getRegion(Range range, IDocument document) {
}

public static Map<String, String> getOptions(FormattingOptions options, ICompilationUnit cu) {
Map<String, String> eclipseOptions = cu.getJavaProject().getOptions(true);
Map<String, String> eclipseOptions = cu.getOptions(true);

Map<String, String> customOptions = options.entrySet().stream().filter(map -> chekIfValueIsNotNull(map.getValue())).collect(toMap(e -> e.getKey(), e -> getOptionValue(e.getValue())));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.JSONUtility;
import org.eclipse.jdt.ls.core.internal.JVMConfigurator;
import org.eclipse.jdt.ls.core.internal.JavaClientConnection;
import org.eclipse.jdt.ls.core.internal.JavaClientConnection.JavaLanguageClient;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.JobHelpers;
Expand Down Expand Up @@ -214,6 +215,11 @@ public void connectClient(JavaLanguageClient client) {
this.documentLifeCycleHandler = new DocumentLifeCycleHandler(this.client, preferenceManager, pm, true);
}

// For testing purpose
public void setClientConnection(JavaClientConnection client) {
this.client = client;
}

//For testing purposes
public void disconnectClient() {
Job.getJobManager().setProgressProvider(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ public static List<SymbolInformation> search(String query, int maxResults, Strin
@Override
public void acceptTypeNameMatch(TypeNameMatch match) {
try {
if (maxResults > 0 && symbols.size() >= maxResults) {
return;
}
Location location = null;
try {
if (!sourceOnly && match.getType().isBinary()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ public boolean isWorkspaceChangeWatchedFilesDynamicRegistered() {
return v3supported && capabilities.getWorkspace() != null && isDynamicRegistrationSupported(capabilities.getWorkspace().getDidChangeWatchedFiles());
}

public boolean isWorkspaceConfigurationSupported() {
return v3supported && capabilities.getWorkspace() != null && isTrue(capabilities.getWorkspace().getConfiguration());
}

public boolean isDocumentSymbolDynamicRegistered() {
return v3supported && isDynamicRegistrationSupported(capabilities.getTextDocument().getDocumentSymbol());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ public class Preferences {
* references.
*/
public static final String JAVA_REFERENCES_INCLUDE_DECOMPILED_SOURCES = "java.references.includeDecompiledSources";
/**
* Insert spaces when pressing Tab
*/
public static final String JAVA_CONFIGURATION_INSERTSPACES = "java.format.insertSpaces";
/**
* Tab Size
*/
public static final String JAVA_CONFIGURATION_TABSIZE = "java.format.tabSize";
/**
* Specifies Java Execution Environments.
*/
Expand Down
3 changes: 3 additions & 0 deletions org.eclipse.jdt.ls.target/org.eclipse.jdt.ls.tp.target
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
<unit id="org.eclipse.equinox.sdk.feature.group" version="0.0.0"/>
<unit id="org.eclipse.jdt.source.feature.group" version="0.0.0"/>
<unit id="org.eclipse.sdk.feature.group" version="0.0.0"/>
<repository location="https://download.eclipse.org/eclipse/updates/4.19-I-builds/I20210217-1800/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
Comment on lines +34 to +36
Copy link
Contributor Author

Choose a reason for hiding this comment

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

4.19M3-I-build contains the dependent formatting changes we made in the upstream jdt.core. But the I-build doesn't contain xtend and xtext sdks, so still need fetch xtend and xtext from the old release. Once 2021-03 release is ready, we can merge these two locations back into one.

<unit id="org.eclipse.xtend.sdk.feature.group" version="0.0.0"/>
<unit id="org.eclipse.xtext.sdk.feature.group" version="0.0.0"/>
<repository location="https://download.eclipse.org/releases/2020-12/202012161000/"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,13 +302,17 @@ protected String evaluateCodeActionCommand(Either<Command, CodeAction> codeActio
Assert.assertNotNull(c.getArguments());
Assert.assertTrue(c.getArguments().get(0) instanceof WorkspaceEdit);
WorkspaceEdit we = (WorkspaceEdit) c.getArguments().get(0);
if (we.getDocumentChanges() != null) {
return ResourceUtils.dos2Unix(evaluateChanges(we.getDocumentChanges()));
return evaluateWorkspaceEdit(we);
}

public static String evaluateWorkspaceEdit(WorkspaceEdit edit) throws JavaModelException, BadLocationException {
if (edit.getDocumentChanges() != null) {
return ResourceUtils.dos2Unix(evaluateChanges(edit.getDocumentChanges()));
}
return ResourceUtils.dos2Unix(evaluateChanges(we.getChanges()));
return ResourceUtils.dos2Unix(evaluateChanges(edit.getChanges()));
}

private String evaluateChanges(List<Either<TextDocumentEdit, ResourceOperation>> documentChanges) throws BadLocationException, JavaModelException {
public static String evaluateChanges(List<Either<TextDocumentEdit, ResourceOperation>> documentChanges) throws BadLocationException, JavaModelException {
List<TextDocumentEdit> changes = documentChanges.stream().filter(e -> e.isLeft()).map(e -> e.getLeft()).collect(Collectors.toList());
assertFalse("No edits generated", changes.isEmpty());
Set<String> uris = changes.stream().map(tde -> tde.getTextDocument().getUri()).distinct().collect(Collectors.toSet());
Expand All @@ -318,15 +322,15 @@ private String evaluateChanges(List<Either<TextDocumentEdit, ResourceOperation>>
return ResourceUtils.dos2Unix(evaluateChanges(uri, edits));
}

protected String evaluateChanges(Map<String, List<TextEdit>> changes) throws BadLocationException, JavaModelException {
public static String evaluateChanges(Map<String, List<TextEdit>> changes) throws BadLocationException, JavaModelException {
Iterator<Entry<String, List<TextEdit>>> editEntries = changes.entrySet().iterator();
Entry<String, List<TextEdit>> entry = editEntries.next();
assertNotNull("No edits generated", entry);
assertEquals("More than one resource modified", false, editEntries.hasNext());
return ResourceUtils.dos2Unix(evaluateChanges(entry.getKey(), entry.getValue()));
}

private String evaluateChanges(String uri, List<TextEdit> edits) throws BadLocationException, JavaModelException {
private static String evaluateChanges(String uri, List<TextEdit> edits) throws BadLocationException, JavaModelException {
assertFalse("No edits generated: " + edits, edits == null || edits.isEmpty());
ICompilationUnit cu = JDTUtils.resolveCompilationUnit(uri);
assertNotNull("CU not found: " + uri, cu);
Expand Down
Loading