eclipse-jdt / eclipse-jdt/eclipse.jdt.core

Organize Imports save action freezes Eclipse

Open
#3,767 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
237
Forks
195
Avg merge
1d 12h
Merged PRs (30d)
47

Description

My Eclipse just froze for 2092 seconds (~35 minutes) doing the "Organize Imports" save action. I did the following steps:
1. Rebase a Git branch to the latest commit
2. Open working tree version of a file changed in this commit
3. Make some whitespace change and save (to trigger the code formatter)

I made some thread dumps during the freeze (added below) which show that the process was busy all time sorting a list of packages and for the comparator opening and reading various ZIP files (likely JARs). This leads to the questions
1. Is the information used for comparison cached or are the zips unpacked for each compare anew?
2. Why is this IO-heavy operation done in the display thread?

I assume that our anti-virus slowed this process down additionally.

# Versions
Eclipse IDE for RCP and RAP Developers (includes Incubating components)
Version: 2024-12 (4.34.0)
Build id: 20241128-0757

org.eclipse.jdt.core 3.40.0.v20241118-1641

openjdk version "21.0.4" 2024-07-16 LTS
OpenJDK Runtime Environment Temurin-21.0.4+7 (build 21.0.4+7-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.4+7 (build 21.0.4+7-LTS, mixed mode, sharing)

Windows 11 Pro 23H2 22631.4890

# Stack traces
after 4:24 min
```
"main" #1 [12652] prio=6 os_prio=0 cpu=148296.88ms elapsed=7341.79s tid=0x000001dfa97e3e60 nid=12652 runnable [0x000000d39bdb9000]
java.lang.Thread.State: RUNNABLE
at java.util.zip.ZipFile$Source.initCEN(java.base@21.0.4/ZipFile.java:1720)
at java.util.zip.ZipFile$Source.(java.base@21.0.4/ZipFile.java:1495)
at java.util.zip.ZipFile$Source.get(java.base@21.0.4/ZipFile.java:1458)
at java.util.zip.ZipFile$CleanableResource.(java.base@21.0.4/ZipFile.java:724)
at java.util.zip.ZipFile.(java.base@21.0.4/ZipFile.java:251)
at java.util.zip.ZipFile.(java.base@21.0.4/ZipFile.java:180)
at java.util.zip.ZipFile.(java.base@21.0.4/ZipFile.java:194)
at org.eclipse.jdt.internal.core.JavaModelManager.getZipFile(JavaModelManager.java:2967)
at org.eclipse.jdt.internal.core.JavaModelManager.getZipFile(JavaModelManager.java:2901)
at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.getJar(JarPackageFragmentRoot.java:259)
at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.computeChildren(JarPackageFragmentRoot.java:129)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.initializePackageNames(JavaProjectElementInfo.java:275)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.getProjectCache(JavaProjectElementInfo.java:243)
at org.eclipse.jdt.internal.core.JavaProject.getProjectCache(JavaProject.java:2364)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.newNameLookup(JavaProjectElementInfo.java:331)
at org.eclipse.jdt.internal.core.JavaProject.newNameLookup(JavaProject.java:2775)
at org.eclipse.jdt.internal.core.JavaProject.newNameLookup(JavaProject.java:2769)
at org.eclipse.jdt.internal.core.JavaProject.newNameLookup(JavaProject.java:2787)
at org.eclipse.jdt.internal.core.JavaProject.newNameLookup(JavaProject.java:2779)
at org.eclipse.jdt.internal.core.JavaProject.findPackageFragment(JavaProject.java:1483)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.PackageImportComparator.determinePackageName(PackageImportComparator.java:52)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.PackageImportComparator.compare(PackageImportComparator.java:40)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.PackageImportComparator.compare(PackageImportComparator.java:1)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportComparator.compare(ImportComparator.java:63)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportComparator.compare(ImportComparator.java:1)
at java.util.TimSort.binarySort(java.base@21.0.4/TimSort.java:296)
at java.util.TimSort.sort(java.base@21.0.4/TimSort.java:239)
at java.util.Arrays.sort(java.base@21.0.4/Arrays.java:1308)
at java.util.ArrayList.sort(java.base@21.0.4/ArrayList.java:1804)
at java.util.Collections.sort(java.base@21.0.4/Collections.java:178)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.ReorderingImportAdder.addImports(ReorderingImportAdder.java:43)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportRewriteAnalyzer.computeImportOrder(ImportRewriteAnalyzer.java:597)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportRewriteAnalyzer.analyzeRewrite(ImportRewriteAnalyzer.java:549)
at org.eclipse.jdt.core.dom.rewrite.ImportRewrite.rewriteImports(ImportRewrite.java:1314)
at org.eclipse.jdt.core.manipulation.OrganizeImportsOperation.createTextEdit(OrganizeImportsOperation.java:648)
at org.eclipse.jdt.internal.corext.fix.ImportsFix.createCleanUp(ImportsFix.java:51)
at org.eclipse.jdt.internal.ui.fix.ImportsCleanUp.createFix(ImportsCleanUp.java:62)
at org.eclipse.jdt.internal.corext.fix.CleanUpRefactoring.calculateChange(CleanUpRefactoring.java:773)
at org.eclipse.jdt.internal.corext.fix.CleanUpPostSaveListener.saved(CleanUpPostSaveListener.java:385)
at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider$4.run(CompilationUnitDocumentProvider.java:1611)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:47)
at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider.notifyPostSaveListeners(CompilationUnitDocumentProvider.java:1605)
at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider.commitWorkingCopy(CompilationUnitDocumentProvider.java:1389)
at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider$3.execute(CompilationUnitDocumentProvider.java:1464)
at org.eclipse.ui.editors.text.TextFileDocumentProvider$DocumentProviderOperation.run(TextFileDocumentProvider.java:133)
at org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation.execute(WorkspaceModifyDelegatingOperation.java:71)
at org.eclipse.ui.actions.WorkspaceModifyOperation.lambda$0(WorkspaceModifyOperation.java:112)
at org.eclipse.ui.actions.WorkspaceModifyOperation$$Lambda/0x000001dfcd03b388.run(Unknown Source)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2457)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2482)
at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:131)
- locked <0x0000000093501470> (a org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation)
at org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner.run(WorkspaceOperationRunner.java:76)
at org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner.run(WorkspaceOperationRunner.java:66)
at org.eclipse.ui.editors.text.TextFileDocumentProvider.executeOperation(TextFileDocumentProvider.java:461)
at org.eclipse.ui.editors.text.TextFileDocumentProvider.saveDocument(TextFileDocumentProvider.java:783)
at org.eclipse.ui.texteditor.AbstractTextEditor.performSave(AbstractTextEditor.java:5019)
at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor.performSave(CompilationUnitEditor.java:1267)
at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor.doSave(CompilationUnitEditor.java:1321)
- locked <0x0000000093501200> (a org.eclipse.jdt.internal.core.CompilationUnit)
at org.eclipse.ui.texteditor.AbstractTextEditor$TextEditorSavable.doSave(AbstractTextEditor.java:7239)
at org.eclipse.ui.Saveable.doSave(Saveable.java:213)
at org.eclipse.ui.internal.SaveableHelper.doSaveModel(SaveableHelper.java:317)
at org.eclipse.ui.internal.SaveableHelper.lambda$1(SaveableHelper.java:195)
at org.eclipse.ui.internal.SaveableHelper$$Lambda/0x000001dfcd36b188.run(Unknown Source)
at org.eclipse.ui.internal.SaveableHelper.lambda$3(SaveableHelper.java:261)
at org.eclipse.ui.internal.SaveableHelper$$Lambda/0x000001dfcd36b3a8.run(Unknown Source)
at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:434)
at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:354)
at org.eclipse.ui.internal.WorkbenchWindow.lambda$7(WorkbenchWindow.java:2341)
at org.eclipse.ui.internal.WorkbenchWindow$$Lambda/0x000001dfcd369bb0.run(Unknown Source)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:67)
at org.eclipse.ui.internal.WorkbenchWindow.run(WorkbenchWindow.java:2338)
at org.eclipse.ui.internal.SaveableHelper.runProgressMonitorOperation(SaveableHelper.java:268)
at org.eclipse.ui.internal.SaveableHelper.saveModels(SaveableHelper.java:206)
at org.eclipse.ui.internal.SaveableHelper.savePart(SaveableHelper.java:150)
at org.eclipse.ui.internal.WorkbenchPage.saveSaveable(WorkbenchPage.java:3819)
at org.eclipse.ui.internal.WorkbenchPage.saveEditor(WorkbenchPage.java:3832)
at org.eclipse.ui.internal.handlers.SaveHandler.execute(SaveHandler.java:81)
at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:277)
at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:98)
at java.lang.invoke.LambdaForm$DMH/0x000001dfcd330c00.invokeVirtual(java.base@21.0.4/LambdaForm$DMH)
at java.lang.invoke.LambdaForm$MH/0x000001dfcd332400.invoke(java.base@21.0.4/LambdaForm$MH)
at java.lang.invoke.Invokers$Holder.invokeExact_MT(java.base@21.0.4/Invokers$Holder)
at jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(java.base@21.0.4/DirectMethodHandleAccessor.java:157)
at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(java.base@21.0.4/DirectMethodHandleAccessor.java:103)
at java.lang.reflect.Method.invoke(java.base@21.0.4/Method.java:580)
at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:299)
at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:233)
at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:174)
at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.execute(HandlerServiceHandler.java:165)
at org.eclipse.core.commands.Command.executeWithChecks(Command.java:488)
at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:485)
at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:204)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.executeCommand(KeyBindingDispatcher.java:308)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.press(KeyBindingDispatcher.java:569)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.processKeyEvent(KeyBindingDispatcher.java:644)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.filterKeySequenceBindings(KeyBindingDispatcher.java:439)
at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher$KeyDownFilter.handleEvent(KeyBindingDispatcher.java:96)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1332)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1172)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1197)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1182)
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1224)
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1220)
at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1703)
at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4854)
at org.eclipse.swt.widgets.Canvas.WM_CHAR(Canvas.java:347)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4732)
at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:342)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:5177)
at org.eclipse.swt.internal.win32.OS.DispatchMessage(Native Method)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3788)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1151)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:663)
at org.eclipse.ui.internal.Workbench$$Lambda/0x000001dfcc2e9be0.run(Unknown Source)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:570)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:178)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:208)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:143)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:109)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:439)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:271)
at java.lang.invoke.DirectMethodHandle$Holder.invokeStatic(java.base@21.0.4/DirectMethodHandle$Holder)
at java.lang.invoke.LambdaForm$MH/0x000001dfcc007800.invoke(java.base@21.0.4/LambdaForm$MH)
at java.lang.invoke.LambdaForm$MH/0x000001dfcc007c00.invokeExact_MT(java.base@21.0.4/LambdaForm$MH)
at jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(java.base@21.0.4/DirectMethodHandleAccessor.java:155)
at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(java.base@21.0.4/DirectMethodHandleAccessor.java:103)
at java.lang.reflect.Method.invoke(java.base@21.0.4/Method.java:580)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:668)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:605)
at org.eclipse.equinox.launcher.Main.run(Main.java:1481)
```
after 11:16 min
```
"main" #1 [12652] prio=6 os_prio=0 cpu=255625.00ms elapsed=7754.61s tid=0x000001dfa97e3e60 nid=12652 runnable [0x000000d39bdba000]
java.lang.Thread.State: RUNNABLE
at java.io.RandomAccessFile.open0(java.base@21.0.4/Native Method)
at java.io.RandomAccessFile.open(java.base@21.0.4/RandomAccessFile.java:356)
at java.io.RandomAccessFile.(java.base@21.0.4/RandomAccessFile.java:273)
at java.io.RandomAccessFile.(java.base@21.0.4/RandomAccessFile.java:223)
at java.util.zip.ZipFile$Source.(java.base@21.0.4/ZipFile.java:1492)
at java.util.zip.ZipFile$Source.get(java.base@21.0.4/ZipFile.java:1458)
at java.util.zip.ZipFile$CleanableResource.(java.base@21.0.4/ZipFile.java:724)
at java.util.zip.ZipFile.(java.base@21.0.4/ZipFile.java:251)
at java.util.zip.ZipFile.(java.base@21.0.4/ZipFile.java:180)
at java.util.zip.ZipFile.(java.base@21.0.4/ZipFile.java:194)
at org.eclipse.jdt.internal.core.JavaModelManager.getZipFile(JavaModelManager.java:2967)
at org.eclipse.jdt.internal.core.JavaModelManager.getZipFile(JavaModelManager.java:2901)
at org.eclipse.jdt.internal.core.util.Util.getJdkLevel(Util.java:905)
at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.computeChildren(JarPackageFragmentRoot.java:124)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.initializePackageNames(JavaProjectElementInfo.java:275)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.getProjectCache(JavaProjectElementInfo.java:243)
at org.eclipse.jdt.internal.core.JavaProject.getProjectCache(JavaProject.java:2364)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.newNameLookup(JavaProjectElementInfo.java:331)
at org.eclipse.jdt.internal.core.JavaProject.newNameLookup(JavaProject.java:2775)
at org.eclipse.jdt.internal.core.JavaProject.newNameLookup(JavaProject.java:2769)
at org.eclipse.jdt.internal.core.JavaProject.newNameLookup(JavaProject.java:2787)
at org.eclipse.jdt.internal.core.JavaProject.newNameLookup(JavaProject.java:2779)
at org.eclipse.jdt.internal.core.JavaProject.findPackageFragment(JavaProject.java:1483)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.PackageImportComparator.determinePackageName(PackageImportComparator.java:52)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.PackageImportComparator.compare(PackageImportComparator.java:40)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.PackageImportComparator.compare(PackageImportComparator.java:1)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportComparator.compare(ImportComparator.java:63)
at org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportComparator.compare(ImportComparator.java:1)
at java.util.TimSort.mergeLo(java.base@21.0.4/TimSort.java:721)
at java.util.TimSort.mergeAt(java.base@21.0.4/TimSort.java:518)
at java.util.TimSort.mergeCollapse(java.base@21.0.4/TimSort.java:448)
at java.util.TimSort.sort(java.base@21.0.4/TimSort.java:245)
at java.util.Arrays.sort(java.base@21.0.4/Arrays.java:1308)
...
```
after 18:14 min
```
"main" #1 [12652] prio=6 os_prio=0 cpu=363921.88ms elapsed=8172.55s tid=0x000001dfa97e3e60 nid=12652 runnable [0x000000d39bdba000]
java.lang.Thread.State: RUNNABLE
at java.util.zip.Inflater.inflateBytesBytes(java.base@21.0.4/Native Method)
at java.util.zip.Inflater.inflate(java.base@21.0.4/Inflater.java:376)
- locked <0x00000000e3cfa818> (a java.util.zip.Inflater$InflaterZStreamRef)
at java.util.zip.InflaterInputStream.read(java.base@21.0.4/InflaterInputStream.java:177)
at java.io.InputStream.readNBytes(java.base@21.0.4/InputStream.java:412)
at java.io.InputStream.readAllBytes(java.base@21.0.4/InputStream.java:349)
at org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(Util.java:436)
at org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(ClassFileReader.java:166)
at org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(ClassFileReader.java:137)
at org.eclipse.jdt.internal.core.util.Util.getJdkLevel(Util.java:910)
at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.computeChildren(JarPackageFragmentRoot.java:124)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.initializePackageNames(JavaProjectElementInfo.java:275)
...
```
after 23:10
```
"main" #1 [12652] prio=6 os_prio=0 cpu=445078.12ms elapsed=8468.50s tid=0x000001dfa97e3e60 nid=12652 runnable [0x000000d39bdb9000]
java.lang.Thread.State: RUNNABLE
at org.eclipse.jdt.internal.core.util.WeakHashSet.get(WeakHashSet.java:160)
at org.eclipse.jdt.internal.core.util.DeduplicationUtil.intern(DeduplicationUtil.java:80)
- locked <0x0000000088a64138> (a org.eclipse.jdt.internal.core.util.WeakHashSet)
at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.unmodifiableCopy(JarPackageFragmentRoot.java:497)
at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.computeChildren(JarPackageFragmentRoot.java:172)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.initializePackageNames(JavaProjectElementInfo.java:275)
...
```
after 29:01
```
"main" #1 [12652] prio=6 os_prio=0 cpu=540578.12ms elapsed=8819.58s tid=0x000001dfa97e3e60 nid=12652 runnable [0x000000d39bdb9000]
java.lang.Thread.State: RUNNABLE
at sun.nio.fs.WindowsPathParser.normalize(java.base@21.0.4/WindowsPathParser.java:210)
at sun.nio.fs.WindowsPathParser.parse(java.base@21.0.4/WindowsPathParser.java:175)
at sun.nio.fs.WindowsPathParser.parse(java.base@21.0.4/WindowsPathParser.java:77)
at sun.nio.fs.WindowsPath.parse(java.base@21.0.4/WindowsPath.java:92)
at sun.nio.fs.WindowsFileSystem.getPath(java.base@21.0.4/WindowsFileSystem.java:231)
at java.nio.file.Path.of(java.base@21.0.4/Path.java:148)
at org.eclipse.jdt.internal.core.util.Util.getEntryName(Util.java:3369)
at org.eclipse.jdt.internal.core.JarPackageFragmentRoot.computeChildren(JarPackageFragmentRoot.java:153)
at org.eclipse.jdt.internal.core.JavaProjectElementInfo.initializePackageNames(JavaProjectElementInfo.java:275)
...
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.