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

ArrayIndexOutOfBoundsException using content assist #808

Closed
Hanksha opened this issue Feb 8, 2019 · 19 comments
Closed

ArrayIndexOutOfBoundsException using content assist #808

Hanksha opened this issue Feb 8, 2019 · 19 comments
Assignees
Labels
Milestone

Comments

@Hanksha
Copy link

Hanksha commented Feb 8, 2019

Hi,

I'm getting an ArrayIndexOutOfBoundsException when using content assist in the Groovy editor. It seems to only happen on objects which have a certain extension method. The exception occurs only right after I press . but not if I trigger content assist manually after typing the first letters.

image

image

java.lang.ArrayIndexOutOfBoundsException: 2
	at org.eclipse.jdt.internal.codeassist.InternalCompletionProposal.findMethodParameterNames(InternalCompletionProposal.java:326)
	at org.eclipse.jdt.internal.codeassist.InternalCompletionProposal.findParameterNames(InternalCompletionProposal.java:942)
	at org.codehaus.groovy.eclipse.codeassist.processors.GroovyCompletionProposal.findParameterNames(GroovyCompletionProposal.java:72)
	at org.eclipse.jdt.ui.text.java.CompletionProposalLabelProvider.appendUnboundedParameterList(CompletionProposalLabelProvider.java:116)
	at org.eclipse.jdt.ui.text.java.CompletionProposalLabelProvider.createMethodProposalLabel(CompletionProposalLabelProvider.java:275)
	at org.eclipse.jdt.ui.text.java.CompletionProposalLabelProvider.createStyledLabel(CompletionProposalLabelProvider.java:581)
	at org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal.computeDisplayString(LazyJavaCompletionProposal.java:267)
	at org.codehaus.groovy.eclipse.codeassist.completions.GroovyJavaMethodCompletionProposal.computeDisplayString(GroovyJavaMethodCompletionProposal.java:178)
	at org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal.getDisplayString(LazyJavaCompletionProposal.java:250)
	at org.codehaus.groovy.eclipse.codeassist.processors.StatementAndExpressionCompletionProcessor.createJavaProposals(StatementAndExpressionCompletionProcessor.java:323)
	at org.codehaus.groovy.eclipse.codeassist.processors.StatementAndExpressionCompletionProcessor.generateProposals(StatementAndExpressionCompletionProcessor.java:266)
	at org.codehaus.groovy.eclipse.codeassist.requestor.GroovyCompletionProposalComputer.computeCompletionProposals(GroovyCompletionProposalComputer.java:216)
	at org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerDescriptor.computeCompletionProposals(CompletionProposalComputerDescriptor.java:336)
	at org.eclipse.jdt.internal.ui.text.java.CompletionProposalCategory.computeCompletionProposals(CompletionProposalCategory.java:340)
	at org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor.collectProposals(ContentAssistProcessor.java:334)
	at org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor.computeCompletionProposals(ContentAssistProcessor.java:291)
	at org.eclipse.jface.text.contentassist.ContentAssistant$2.lambda$0(ContentAssistant.java:2014)
	at java.util.Collections$SingletonSet.forEach(Collections.java:4767)
	at org.eclipse.jface.text.contentassist.ContentAssistant$2.run(ContentAssistant.java:2013)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
	at org.eclipse.jface.text.contentassist.ContentAssistant.computeCompletionProposals(ContentAssistant.java:2010)
	at org.eclipse.jface.text.contentassist.CompletionProposalPopup.computeProposals(CompletionProposalPopup.java:573)
	at org.eclipse.jface.text.contentassist.CompletionProposalPopup.lambda$0(CompletionProposalPopup.java:503)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:72)
	at org.eclipse.jface.text.contentassist.CompletionProposalPopup.showProposals(CompletionProposalPopup.java:498)
	at org.eclipse.jface.text.contentassist.ContentAssistant.showPossibleCompletions(ContentAssistant.java:1824)
	at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor$AdaptedSourceViewer.doOperation(CompilationUnitEditor.java:189)
	at org.eclipse.ui.texteditor.ContentAssistAction.lambda$0(ContentAssistAction.java:85)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:72)
	at org.eclipse.ui.texteditor.ContentAssistAction.run(ContentAssistAction.java:84)
	at org.eclipse.jface.action.Action.runWithEvent(Action.java:476)
	at org.eclipse.jface.commands.ActionHandler.execute(ActionHandler.java:121)

I'm using Eclipse 4.10.

@eric-milles
Copy link
Member

Can you share the expression you are trying to complete when this exception occurs? I am not seeing it on the "". completion from your example. Also, if you could disable substring proposals (Window > Preferences > Java >Editor > Content Assist > Show substring matches) and then cycle through "expr.a|" (Ctrl+Space) to "expr.z|" (Ctrl+Space), that would help pin down which extension method may be at fault.

@eric-milles eric-milles added the bug label Feb 8, 2019
@Hanksha
Copy link
Author

Hanksha commented Feb 11, 2019

I was able to find an extension method which triggers the exception consistently.
Which is ''.cacheGe

Note that if I complete the method name like this ''.cacheGet I get no proposals.

image

(That's with Show substring matches disabled)

@eric-milles
Copy link
Member

What library is CacheMethods from? I'd like to import it to have access to cacheGet.

@Hanksha
Copy link
Author

Hanksha commented Feb 11, 2019

The source code for this class is not public and the jar is not published on a public mvn repo either.

Only alternative would be to download it from our update site and extract it from the plugin jar packing it (after extraction it's in /lib/toro-integrate-core-api-3.2.0-jar-with-dependencies.jar) but that's a 64mb download.

@eric-milles
Copy link
Member

It looks like toro-integrate-core-api-3.2.0-jar-with-dependencies.jar contains Groovy dependencies in addition to some other stuff. Is this the source of your Groovy classes in your project? That is, do you have no other dependency to groovy-all or Groovy Libraries classpath container?

My intuition is that the lack of sources is the result of the issue. I'm setting up a small project with only the toro library to test that out.

@eric-milles eric-milles self-assigned this Feb 11, 2019
@Hanksha
Copy link
Author

Hanksha commented Feb 12, 2019

The .classpath is:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
	<classpathentry exported="true" kind="con" path="GROOVY_SUPPORT"/>
	<classpathentry exported="true" kind="con" path="GROOVY_DSL_SUPPORT"/>
	<classpathentry kind="lib" path="/Applications/TORO Coder Studio.app/Contents/Eclipse/plugins/io.toro.coder.core_1.5.0.201902080847/lib/toro-integrate-core-api-3.2.0-jar-with-dependencies.jar">
		<attributes>
			<attribute name="javadoc_location" value="https://javadocs.torocloud.com/integrate/3.2.0"/>
		</attributes>
	</classpathentry>
	<classpathentry kind="output" path=".bin"/>
</classpath>

@eric-milles
Copy link
Member

Thanks for that info. Could you try two separate things for me?

  1. Remove the GROOVY_SUPPORT container entry. It is redundant since toro integrate embeds Groovy.
  2. Comment out or remove the javadoc link for toro integrate. I'm wondering if http URL is why parameter name retrieval is failing.

@Hanksha
Copy link
Author

Hanksha commented Feb 12, 2019

If I remove the javadoc link the error is not showing anymore.

@eric-milles
Copy link
Member

Okay, here's what is going on. This section of BinaryMethod.getParameterNames() is trying to parse the param names out of the retrieved javadoc string (included below). methodDoc.indexOf(')', indexOfOpenParen) is returning the index of the closing paren of the first annotation and it goes off the rails form there, ending up with parameter names: [package", arg1].

<ul class="blockList">
<li class="blockList">
<h4>cachePut</h4>
<pre>@GloopComment(value="Puts the value in the cache for with given key.")
public static&nbsp;void&nbsp;cachePut(@GloopParameter(value="Cache name in the current package",allowNull=false)
                                                                                                   <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;cacheName,
                                                                                                   @GloopParameter(value="The cache key",allowNull=false)
                                                                                                   <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a>&nbsp;key,
                                                                                                   @GloopParameter(value="The cache value",allowNull=false)
                                                                                                   <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a>&nbsp;value)</pre>
<dl>
<dt><span class="paramLabel">Parameters:</span></dt>
<dd><code>cacheName</code> - Cache name in the current package</dd>
<dd><code>key</code> - The cache key</dd>
<dd><code>value</code> - The cache value</dd>
</dl>
</li>
</ul>

		if (methodDoc != null) {
			int indexOfOpenParen = methodDoc.indexOf('(');
			// Annotations may have parameters, so make sure we are parsing the actual method parameters.
			if (info.getAnnotations() != null) {
				while (indexOfOpenParen != -1 && !isOpenParenForMethod(methodDoc, getElementName(), indexOfOpenParen)) {
					indexOfOpenParen = methodDoc.indexOf('(', indexOfOpenParen + 1);
				}
			}
			if (indexOfOpenParen != -1) {
				final int indexOfClosingParen = methodDoc.indexOf(')', indexOfOpenParen);
				if (indexOfClosingParen != -1) {
					final char[] paramsSource =
						CharOperation.replace(
							methodDoc.substring(indexOfOpenParen + 1, indexOfClosingParen).toCharArray(),
							"&nbsp;".toCharArray(), //$NON-NLS-1$
							new char[] {' '});
					final char[][] params = splitParameters(paramsSource, paramCount);
					final int paramsLength = params.length;
					String[] names = new String[paramsLength];
					for (int i = 0; i < paramsLength; i++) {
						final char[] param = params[i];
						int indexOfSpace = CharOperation.lastIndexOf(' ', param);
						if (indexOfSpace != -1) {
							names[i] = String.valueOf(param, indexOfSpace + 1, param.length - indexOfSpace -1);
						} else {
							names[i] = "arg" + i; //$NON-NLS-1$
						}
					}
					return this.parameterNames = names;
				}
			}
		}

@eric-milles
Copy link
Member

@eric-milles
Copy link
Member

Ready to test

@Hanksha
Copy link
Author

Hanksha commented Feb 12, 2019

How do I test? Is it in one of the snapshot builds or release builds?

@eric-milles
Copy link
Member

Usually the Check for Updates menu command finds and installs the new version.

@Hanksha
Copy link
Author

Hanksha commented Feb 13, 2019

Yes just saw that it built on Bamboo.

@eric-milles
Copy link
Member

Depending on the version of eclipse platform you have, you can get the latest build from one of these update sites:

Eclipse Level Snapshot Update Site
4.11 (2019-03) http://dist.springsource.org/snapshot/GRECLIPSE/e4.11
4.10 (2018-12) http://dist.springsource.org/snapshot/GRECLIPSE/e4.10
4.9 (2018-09) http://dist.springsource.org/snapshot/GRECLIPSE/e4.9
4.8 (Photon) http://dist.springsource.org/snapshot/GRECLIPSE/e4.8
4.7 (Oxygen) http://dist.springsource.org/snapshot/GRECLIPSE/e4.7

@eric-milles eric-milles added this to the v3.3.0 milestone Feb 13, 2019
@Hanksha
Copy link
Author

Hanksha commented Feb 14, 2019

Sorry for the late reply, other stuff came up.

I was able to test it, so the expression ''.cacheGe doesn't throw an exception anymore but ''. still does. Maybe another method is causing a similar issue.

@Hanksha
Copy link
Author

Hanksha commented Feb 14, 2019

The expression that triggers the exception this time is ''.getD.

image
The expressions ''.getDi and ''.getDo don't throw and exception.

@eric-milles
Copy link
Member

Ready to re-test

@Hanksha
Copy link
Author

Hanksha commented Feb 15, 2019

It's fixed, no more error :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants