Skip to content

Commit

Permalink
add custom folding regions
Browse files Browse the repository at this point in the history
  • Loading branch information
danthe1st committed Dec 4, 2024
1 parent e57bf66 commit 0301e82
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 23 deletions.
2 changes: 1 addition & 1 deletion org.eclipse.jdt.ui/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Automatic-Module-Name: org.eclipse.jdt.ui
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.ui; singleton:=true
Bundle-Version: 3.33.300.qualifier
Bundle-Version: 3.34.0.qualifier
Bundle-Activator: org.eclipse.jdt.internal.ui.JavaPlugin
Bundle-ActivationPolicy: lazy
Bundle-Vendor: %providerName
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.jdt.ui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.ui</artifactId>
<version>3.33.300-SNAPSHOT</version>
<version>3.34.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@

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

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
Expand All @@ -27,6 +27,7 @@
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import org.eclipse.jface.preference.IPreferenceStore;

Expand Down Expand Up @@ -59,6 +60,12 @@ public void widgetSelected(SelectionEvent e) {
fOverlayStore.setValue(fCheckBoxes.get(button), button.getSelection());
}
};
private Map<Text, String> fStringInputs= new HashMap<>();
private ModifyListener fModifyListener = e -> {
Text text = (Text)e.widget;
fOverlayStore.setValue(fStringInputs.get(text), text.getText());
};



public DefaultJavaFoldingPreferenceBlock() {
Expand All @@ -75,6 +82,8 @@ private OverlayKey[] createKeys() {
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_METHODS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_IMPORTS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_HEADERS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_START));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_END));

return overlayKeys.toArray(new OverlayKey[overlayKeys.size()]);
}
Expand All @@ -87,22 +96,36 @@ public Control createControl(Composite composite) {
fOverlayStore.load();
fOverlayStore.start();

Composite inner= new Composite(composite, SWT.NONE);
GridLayout layout= new GridLayout(1, true);
layout.verticalSpacing= 3;
layout.marginWidth= 0;
inner.setLayout(layout);

Label label= new Label(inner, SWT.LEFT);
label.setText(FoldingMessages.DefaultJavaFoldingPreferenceBlock_title);

addCheckBox(inner, FoldingMessages.DefaultJavaFoldingPreferenceBlock_comments, PreferenceConstants.EDITOR_FOLDING_JAVADOC, 0);
addCheckBox(inner, FoldingMessages.DefaultJavaFoldingPreferenceBlock_headers, PreferenceConstants.EDITOR_FOLDING_HEADERS, 0);
addCheckBox(inner, FoldingMessages.DefaultJavaFoldingPreferenceBlock_innerTypes, PreferenceConstants.EDITOR_FOLDING_INNERTYPES, 0);
addCheckBox(inner, FoldingMessages.DefaultJavaFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0);
addCheckBox(inner, FoldingMessages.DefaultJavaFoldingPreferenceBlock_imports, PreferenceConstants.EDITOR_FOLDING_IMPORTS, 0);

return inner;
Composite outer= new Composite(composite, SWT.NONE);
outer.setLayout(layout);

Composite initialFoldingComposite= new Composite(outer, SWT.NONE);
initialFoldingComposite.setLayout(layout);

Label initialFoldLabel= new Label(initialFoldingComposite, SWT.LEFT);
initialFoldLabel.setText(FoldingMessages.DefaultJavaFoldingPreferenceBlock_title);

addCheckBox(initialFoldingComposite, FoldingMessages.DefaultJavaFoldingPreferenceBlock_comments, PreferenceConstants.EDITOR_FOLDING_JAVADOC, 0);
addCheckBox(initialFoldingComposite, FoldingMessages.DefaultJavaFoldingPreferenceBlock_headers, PreferenceConstants.EDITOR_FOLDING_HEADERS, 0);
addCheckBox(initialFoldingComposite, FoldingMessages.DefaultJavaFoldingPreferenceBlock_innerTypes, PreferenceConstants.EDITOR_FOLDING_INNERTYPES, 0);
addCheckBox(initialFoldingComposite, FoldingMessages.DefaultJavaFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0);
addCheckBox(initialFoldingComposite, FoldingMessages.DefaultJavaFoldingPreferenceBlock_imports, PreferenceConstants.EDITOR_FOLDING_IMPORTS, 0);

Composite customRegionComposite= new Composite(outer, SWT.NONE);
GridLayout customRegionLayout= new GridLayout(2, false);
customRegionLayout.verticalSpacing= 3;
customRegionLayout.marginWidth= 0;
customRegionComposite.setLayout(customRegionLayout);
Label customRegionLabel= new Label(customRegionComposite, SWT.LEFT);
customRegionLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false, 2, 1));
customRegionLabel.setText(FoldingMessages.DefaultJavaFoldingPreferenceBlock_custom_region_title);
addStringInput(customRegionComposite, FoldingMessages.DefaultJavaFoldingPreferenceBlock_CustomRegionStart, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_START);
addStringInput(customRegionComposite, FoldingMessages.DefaultJavaFoldingPreferenceBlock_CustomRegionEnd, PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_END);
return outer;
}

private Button addCheckBox(Composite parent, String label, String key, int indentation) {
Expand All @@ -121,13 +144,29 @@ private Button addCheckBox(Composite parent, String label, String key, int inden
return checkBox;
}

private void addStringInput(Composite parent, String label, String key) {
Label labelElement = new Label(parent, SWT.LEFT);
labelElement.setText(label);
GridData labelGridData= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
labelGridData.horizontalSpan= 1;
labelGridData.grabExcessVerticalSpace= false;
labelElement.setLayoutData(labelGridData);

Text textInput = new Text(parent, SWT.SINGLE | SWT.BORDER);
textInput.setText(label);
textInput.addModifyListener(fModifyListener);

GridData textGridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
textGridData.horizontalSpan= 1;
textGridData.grabExcessVerticalSpace= true;
textInput.setLayoutData(textGridData);

fStringInputs.put(textInput, key);
}

private void initializeFields() {
Iterator<Button> it= fCheckBoxes.keySet().iterator();
while (it.hasNext()) {
Button b= it.next();
String key= fCheckBoxes.get(b);
b.setSelection(fOverlayStore.getBoolean(key));
}
fCheckBoxes.forEach((b, key) -> b.setSelection(fOverlayStore.getBoolean(key)));
fStringInputs.forEach((text, key) -> text.setText(fOverlayStore.getString(key)));
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ private FoldingMessages() {
public static String DefaultJavaFoldingPreferenceBlock_methods;
public static String DefaultJavaFoldingPreferenceBlock_imports;
public static String DefaultJavaFoldingPreferenceBlock_headers;

public static String DefaultJavaFoldingPreferenceBlock_custom_region_title;
public static String DefaultJavaFoldingPreferenceBlock_CustomRegionStart;
public static String DefaultJavaFoldingPreferenceBlock_CustomRegionEnd;
public static String EmptyJavaFoldingPreferenceBlock_emptyCaption;
public static String JavaFoldingStructureProviderRegistry_warning_providerNotFound_resetToDefault;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ DefaultJavaFoldingPreferenceBlock_methods= &Members
DefaultJavaFoldingPreferenceBlock_imports= &Imports
DefaultJavaFoldingPreferenceBlock_headers= &Header Comments

DefaultJavaFoldingPreferenceBlock_custom_region_title=Custom regions:
DefaultJavaFoldingPreferenceBlock_CustomRegionStart= Start of custom folding regions
DefaultJavaFoldingPreferenceBlock_CustomRegionEnd= End of custom folding region

JavaFoldingStructureProviderRegistry_warning_providerNotFound_resetToDefault= The ''{0}'' folding provider could not be found. Resetting to the default folding provider.

EmptyJavaFoldingPreferenceBlock_emptyCaption=
22 changes: 22 additions & 0 deletions org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/PreferenceConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -3471,6 +3471,26 @@ private PreferenceConstants() {
*/
public static final String EDITOR_FOLDING_HEADERS= "editor_folding_default_headers"; //$NON-NLS-1$

/**
* A named preference that stores the value for the start indicator of custom folding regions for the default folding provider.
* <p>
* Value is of type <code>String</code>.
* </p>
*
* @since 3.34
*/
public static final String EDITOR_FOLDING_CUSTOM_REGION_START= "editor_folding_custom_region_start"; //$NON-NLS-1$

/**
* A named preference that stores the value for the end indicator of custom folding regions for the default folding provider.
* <p>
* Value is of type <code>String</code>.
* </p>
*
* @since 3.34
*/
public static final String EDITOR_FOLDING_CUSTOM_REGION_END= "editor_folding_custom_region_end"; //$NON-NLS-1$

/**
* A named preference that holds the methods or types whose methods are by default expanded with
* constructors in the Call Hierarchy.
Expand Down Expand Up @@ -4288,6 +4308,8 @@ public static void initializeDefaultValues(IPreferenceStore store) {
store.setDefault(PreferenceConstants.EDITOR_FOLDING_METHODS, false);
store.setDefault(PreferenceConstants.EDITOR_FOLDING_IMPORTS, true);
store.setDefault(PreferenceConstants.EDITOR_FOLDING_HEADERS, true);
store.setDefault(PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_START, "#region"); //$NON-NLS-1$
store.setDefault(PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_END, "#endregion"); //$NON-NLS-1$

// properties file editor
store.setDefault(PreferenceConstants.PROPERTIES_FILE_COLORING_KEY_BOLD, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
*******************************************************************************/
package org.eclipse.jdt.ui.text.folding;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
Expand Down Expand Up @@ -107,6 +109,8 @@ protected final class FoldingStructureComputationContext {
private IScanner fDefaultScanner; // this one may or not be the shared DefaultJavaFoldingStructureProvider.fSharedScanner
private IScanner fScannerForProject;

private Deque<Integer> customRegions = new ArrayDeque<>();

private FoldingStructureComputationContext(IDocument document, ProjectionAnnotationModel model, boolean allowCollapsing, IScanner scanner) {
Assert.isNotNull(document);
Assert.isNotNull(model);
Expand Down Expand Up @@ -734,6 +738,10 @@ public void projectionDisabled() {
private boolean fCollapseMembers= false;
private boolean fCollapseHeaderComments= true;

private boolean fCustomFoldingRegionsEnabled=true;
private String fCustomFoldingRegionBegin="#region"; //$NON-NLS-1$
private String fCustomFoldingRegionEnd="#endregion"; //$NON-NLS-1$

/* filters */
/** Member filter, matches nested members (but not top-level types). */
private final Filter fMemberFilter = new MemberFilter();
Expand Down Expand Up @@ -906,6 +914,10 @@ private void initializePreferences() {
fCollapseJavadoc= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_JAVADOC);
fCollapseMembers= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS);
fCollapseHeaderComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS);
fCustomFoldingRegionBegin=store.getString(PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_START);
fCustomFoldingRegionEnd=store.getString(PreferenceConstants.EDITOR_FOLDING_CUSTOM_REGION_END);
fCustomFoldingRegionsEnabled = !fCustomFoldingRegionBegin.isEmpty() && !fCustomFoldingRegionEnd.isEmpty() &&
!fCustomFoldingRegionBegin.contains(fCustomFoldingRegionEnd) && !fCustomFoldingRegionEnd.contains(fCustomFoldingRegionBegin);
}

private void update(FoldingStructureComputationContext ctx) {
Expand Down Expand Up @@ -1151,6 +1163,7 @@ protected final IRegion[] computeProjectionRanges(ISourceReference reference, Fo
scanner.resetTo(shift, shift + range.getLength());

int start= shift;

while (true) {

int token= scanner.getNextToken();
Expand All @@ -1162,17 +1175,45 @@ protected final IRegion[] computeProjectionRanges(ISourceReference reference, Fo
case ITerminalSymbols.TokenNameCOMMENT_BLOCK: {
int end= scanner.getCurrentTokenEndPosition() + 1;
regions.add(new Region(start, end - start));
continue;
}
case ITerminalSymbols.TokenNameCOMMENT_LINE:
//$FALL-THROUGH$
case ITerminalSymbols.TokenNameCOMMENT_LINE: {
if (fCustomFoldingRegionsEnabled) {
checkCustomFolding(ctx, regions, scanner, start, regions.size());
}
continue;
}
}

break;
}

regions.add(new Region(start, shift + range.getLength() - start));

if (fCustomFoldingRegionsEnabled) {
if (reference instanceof IJavaElement javaElement && javaElement.getParent() != null && javaElement.getParent() instanceof IParent parent) {
IJavaElement[] siblings= parent.getChildren();
if (javaElement == siblings[siblings.length-1] && parent instanceof ISourceReference parentSourceReference) {
int regionStart = range.getOffset() + range.getLength();
ISourceRange parentRange= parentSourceReference.getSourceRange();
int regionEnd = parentRange.getOffset() + parentRange.getLength();
scanner.resetTo(regionStart, regionEnd);
for(int token = scanner.getNextToken(); token != ITerminalSymbols.TokenNameEOF; token=scanner.getNextToken()) {
if(isCommentToken(token)) {
checkCustomFolding(ctx, regions, scanner, scanner.getCurrentTokenStartPosition(), regions.size()-1);
}
}
}
}
if (reference instanceof IParent parent && !parent.hasChildren()) {
for(int token = scanner.getNextToken(); token != ITerminalSymbols.TokenNameEOF; token=scanner.getNextToken()) {
if(isCommentToken(token)) {
checkCustomFolding(ctx, regions, scanner, scanner.getCurrentTokenStartPosition(), regions.size()-1);
}
}
}
}

IRegion[] result= new IRegion[regions.size()];
regions.toArray(result);
return result;
Expand All @@ -1182,6 +1223,22 @@ protected final IRegion[] computeProjectionRanges(ISourceReference reference, Fo
return new IRegion[0];
}

private boolean isCommentToken(int token) {
return token == ITerminalSymbols.TokenNameCOMMENT_BLOCK || token == ITerminalSymbols.TokenNameCOMMENT_JAVADOC || token == ITerminalSymbols.TokenNameCOMMENT_MARKDOWN || token == ITerminalSymbols.TokenNameCOMMENT_LINE;
}

private void checkCustomFolding(FoldingStructureComputationContext ctx, List<IRegion> regions, IScanner scanner, int start, int regionArrayIndex) {
String currentTokenSource = new String(scanner.getCurrentTokenSource());
if (currentTokenSource.contains(fCustomFoldingRegionBegin)) {
ctx.customRegions.add(start);
}
if (currentTokenSource.contains(fCustomFoldingRegionEnd) && !ctx.customRegions.isEmpty()) {
int end= scanner.getCurrentTokenEndPosition() + 1;
Integer regionStart= ctx.customRegions.removeLast();
regions.add(regionArrayIndex, new Region(regionStart, end - regionStart));
}
}

private IRegion computeHeaderComment(FoldingStructureComputationContext ctx) throws JavaModelException {
// search at most up to the first type
ISourceRange range= ctx.getFirstType().getSourceRange();
Expand Down

0 comments on commit 0301e82

Please sign in to comment.