Bug 83565 - BCException "bad type name" thrown when compiling
Summary: BCException "bad type name" thrown when compiling
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 1.5.0 M3   Edit
Assignee: Andrew Clement CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-01-24 17:13 EST by Andrew Eisenberg CLA
Modified: 2005-06-03 11:34 EDT (History)
1 user (show)

See Also:


Attachments
AspectJ Eclipse project illustrating the bug (550 bytes, application/x-compressed)
2005-05-06 22:48 EDT, Joshua Davis CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Eisenberg CLA 2005-01-24 17:13:15 EST
I just downloaded AJDT version 1.2.0.20050124144759 and I am running Eclipse
3.1M4.  I tried to use aspectJ on an existing Java 5 project.  There are no
aspects in it yet, just straight Java 5.  The project runs just fine as a
standard Java project. 

When add the AspectJ nature and I try to compile the project, no class files are
generated and I get this error generated on a type that is parameterized:

Internal compiler error
org.aspectj.weaver.BCException: Bad type name: 

	at org.aspectj.weaver.TypeX.nameToSignature(TypeX.java:634)

	at org.aspectj.weaver.TypeX.forName(TypeX.java:87)

	at
org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory.fromBinding(EclipseFactory.java:155)

	at
org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory.fromBindings(EclipseFactory.java:163)

	at
org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory.makeResolvedMember(EclipseFactory.java:229)

	at
org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory.makeResolvedMember(EclipseFactory.java:224)

	at
org.aspectj.ajdt.internal.core.builder.AsmHierarchyBuilder.visit(AsmHierarchyBuilder.java:675)

	at
org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration.traverse(ConstructorDeclaration.java:447)

	at
org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.traverse(TypeDeclaration.java:1133)

	at
org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.traverse(CompilationUnitDeclaration.java:314)

	at
org.aspectj.ajdt.internal.core.builder.AsmHierarchyBuilder.internalBuild(AsmHierarchyBuilder.java:171)

	at
org.aspectj.ajdt.internal.core.builder.AsmHierarchyBuilder.buildStructureForCompilationUnit(AsmHierarchyBuilder.java:111)

	at
org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory.finishedCompilationUnit(EclipseFactory.java:354)

	at
org.aspectj.ajdt.internal.compiler.AjCompilerAdapter.afterProcessing(AjCompilerAdapter.java:138)

	at
org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:373)

	at
org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:682)

	at
org.aspectj.ajdt.internal.core.builder.AjBuildManager.doBuild(AjBuildManager.java:168)

	at
org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:102)

	at org.aspectj.ajde.internal.CompilerAdapter.compile(CompilerAdapter.java:122)

	at
org.aspectj.ajde.internal.AspectJBuildManager$CompilerThread.run(AspectJBuildManager.java:165)


The source code of the file that generates this error is:

package mj.compiler.ast;

import java.util.Vector;

import mj.compiler.Driver;
import mj.compiler.Visitor;

public class Sequence<T extends AST> extends AST {
	
	private Vector<T> elements = new Vector<T>();
	
	public Sequence() {
		super(0, 0);
    }
	
	public Sequence(T element) {
		super(element);
		elements.add(element);
    }
    
	public int length()       { return elements.size(); }
	public T elementAt(int i) { return elements.elementAt(i); }

    public Sequence add(T element) {
    	elements.add(element);
		return this;
    }
    
    public Sequence add(int pos, T element) {
    	elements.add(pos, element);
    	return this;
    }
    
    public Sequence addAll(Sequence<T> others) {		
		if(  others == null ) return this;
		elements.addAll(others.elements);
		return this;
    }
    
    public void visitChildren(Visitor v) {
    	for( AST element : elements ) {
    		element.visit(v);
        }
    }
    
    public void replaceChild(AST old, AST gnu) {
    	T NEW = (T)gnu;
    	for(int i = 0; i < elements.size(); i++ ) {
    		if( elements.get(i) == old ) {
    			elements.set(i, NEW);
    			return;
    		}
    	}
    	throw new Driver.CompileError("Can't find child in replaceChild.");
    }

	/*** START GENERATED VISITOR PROTOCOL ***///TODO
    public void visit(mj.compiler.Visitor v) {
        v.visitSequence(this);
    }
	/*** END GENERATED VISITOR PROTOCOL ***/
}


Hope this helps something.

ps- I am able to create and run a very simple AspectJ project with an aspect,
advice, and some Java 5 syntax.
Comment 1 Adrian Colyer CLA 2005-01-24 17:21:37 EST
This looks like the weaver code that builds the structure model for ajdt is
choking on some generic type name its not expecting to see. I'm reassigning to
Andy temporarily as I'm on a plane the next two days...
Comment 2 Andrew Clement CLA 2005-01-25 03:57:53 EST
I've recreated from the command line by compiling that type with -emacssym
(which generated the ASM).  Adrian is correct that we choke on the generic
signature.

Although not all that helpful a temporary workaround is to turn off structure
model building in the project properties, it should then compile the code
successfully (but the xref view will be empty...)
Comment 3 Mik Kersten CLA 2005-01-25 11:57:30 EST
I think I know what's going wrong here and will plan on fixing it this week.
Comment 4 Mik Kersten CLA 2005-01-27 12:13:01 EST
Andy: the ASM part of this is fixed, but note the following caveat.

The problem was that the weaver's TypeX.nameToSignature(String name) can't 
handle generic return types, for example the "T" in:

public T elementAt(int i) {
  return elements.elementAt(i);
}

I've made the AsmHierarchyBuilder robust to that problem, which means that 
when building a signature it will put <undefined> whenever the weaver can't 
resolve a name.  I committed a minimal test of this to, which now passes (if 
the single test is uncommented and 1.5 is required).

/ajde/testsrc/org/aspectj/ajde/GenericsTest.java

Note that the hierarchy of the structure model is correct, although it would 
be nice to get the right type name in there for clients that make use the 
bytecode signature.  I'll leave this open in case you want to use this test 
case to experiment.  In that case you may also want to inspect the catch catch
(BCException) clause in AsmHierarchyBuilder.
Comment 5 Adrian Colyer CLA 2005-03-23 09:19:21 EST
lets take one more look at this one before closing out m2...
Comment 6 Adrian Colyer CLA 2005-03-23 15:33:39 EST
the fix for bug 843333 should ensure that TypeX.forName never sees a
parameterized type. This is certainly good enough for m2. Moving the bug to m3
where we will pass parameterized types through in all probability.
Comment 7 Joshua Davis CLA 2005-05-03 17:15:42 EDT
(In reply to comment #4)
> The problem was that the weaver's TypeX.nameToSignature(String name) can't 
> handle generic return types, for example the "T" in:
> 
> public T elementAt(int i) {
>   return elements.elementAt(i);
> }
I've encountered the same problem using AJDT 1.2.0.200503135046 AND Eclipse
3.1M6, only my class has no methods with a generic return type or generic
parameters.

=== Source for my file ===
package com.merklenet.test.mock;

import java.rmi.MarshalledObject;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.merklenet.knowledgelink.prototype.framework.Envelope;
import com.merklenet.knowledgelink.prototype.framework.ServiceIdentifier;

import net.jini.core.entry.Entry;
import net.jini.core.entry.UnusableEntryException;
import net.jini.core.event.EventRegistration;
import net.jini.core.event.RemoteEventListener;
import net.jini.core.lease.Lease;
import net.jini.core.transaction.Transaction;
import net.jini.core.transaction.TransactionException;
import net.jini.space.JavaSpace;

public class MockJavaSpaceForEnvelopes implements JavaSpace {
   private Map<ServiceIdentifier, Set<Envelope>> envelopes = 
      new HashMap<ServiceIdentifier, Set<Envelope>>();

   public MockJavaSpaceForEnvelopes() {
      super();
   }

   public Lease write(Entry entry, Transaction txn, long lease) 
      throws TransactionException, RemoteException 
   {
      return write((Envelope) entry, txn, lease);
   }

   public Lease write(Envelope entry, Transaction txn, long lease) 
         throws TransactionException, RemoteException 
   {
      synchronized (envelopes) {
         Set<Envelope> envelopesForService = getEnvelopeSetForTemplate(entry);
         envelopesForService.add(entry);
         envelopes.notify();
      }
      return null;
   }

   private Set<Envelope> getEnvelopeSetForTemplate(Envelope entry) {
      Set<Envelope> envelopesForService = envelopes.get(entry.currentAddressee);
      if (envelopesForService == null) {
         envelopesForService = new HashSet<Envelope>();
         envelopes.put(entry.currentAddressee, envelopesForService);
      }
      return envelopesForService;
   }

   public Entry read(Entry tmpl, Transaction txn, long timeout) 
         throws UnusableEntryException, TransactionException, 
            InterruptedException, RemoteException 
   {
      return read((Envelope) tmpl, txn, timeout);
   }

   public Entry read(Envelope tmpl, Transaction txn, long timeout) 
      throws UnusableEntryException, TransactionException, 
         InterruptedException, RemoteException 
   {
      synchronized (envelopes) {
         if (getEnvelopeSetForTemplate(tmpl).isEmpty()) {
            envelopes.wait(timeout);
         }
         return readIfExists(tmpl, txn, timeout);
      }
   }

   public Entry readIfExists(Entry tmpl, Transaction txn, long timeout) 
      throws UnusableEntryException, TransactionException, 
         InterruptedException, RemoteException 
   {
      return readIfExists((Envelope) tmpl, txn, timeout);
   }

   public Entry readIfExists(Envelope tmpl, Transaction txn, long timeout) 
      throws UnusableEntryException, TransactionException, 
         InterruptedException, RemoteException 
   {
      synchronized (envelopes) {
         Set<Envelope> envelopeSetForTemplate = getEnvelopeSetForTemplate(tmpl);
         if (envelopeSetForTemplate.isEmpty())
            return null;
         return envelopeSetForTemplate.iterator().next();
      }
   }

   public Entry take(Entry tmpl, Transaction txn, long timeout) 
      throws UnusableEntryException, TransactionException, 
         InterruptedException, RemoteException 
   {
      return take((Envelope) tmpl, txn, timeout);
   }

   public Entry take(Envelope tmpl, Transaction txn, long timeout) 
      throws UnusableEntryException, TransactionException, 
         InterruptedException, RemoteException 
   {
      synchronized (envelopes) {
         if (getEnvelopeSetForTemplate(tmpl).isEmpty()) {
            envelopes.wait(timeout);
         }
         return takeIfExists(tmpl, txn, timeout);
      }
   }

   public Entry takeIfExists(Entry tmpl, Transaction txn, long timeout) 
      throws UnusableEntryException, TransactionException, 
         InterruptedException, RemoteException 
   {
      return takeIfExists((Envelope) tmpl, txn, timeout);
   }

   public Entry takeIfExists(Envelope tmpl, Transaction txn, long timeout) 
      throws UnusableEntryException, TransactionException, 
         InterruptedException, RemoteException 
   {
      synchronized (envelopes) {
         Set<Envelope> envelopeSetForTemplate = getEnvelopeSetForTemplate(tmpl);
         if (envelopeSetForTemplate.isEmpty())
            return null;
         Entry result = envelopeSetForTemplate.iterator().next();
         envelopeSetForTemplate.remove(result);
         return result;
      }
   }

   public EventRegistration notify(Entry tmpl, Transaction txn, 
         RemoteEventListener listener, long lease, MarshalledObject handback) 
      throws TransactionException, RemoteException 
   {
      throw new UnsupportedOperationException("notify");
   }

   public Entry snapshot(Entry e) throws RemoteException {
      throw new UnsupportedOperationException("snapshot");
   }
}
======
Comment 8 Andrew Clement CLA 2005-05-06 11:36:16 EDT
The failing code has now be upgraded to support basic generics - the use of
parameterized types and raw types *should* be ok... so this might be resolved in
the next version of AJDT...  unfortunately without a simple testcase I can't
confirm that right now...
Comment 9 Joshua Davis CLA 2005-05-06 22:48:06 EDT
Created attachment 20796 [details]
AspectJ Eclipse project illustrating the bug
Comment 10 Joshua Davis CLA 2005-05-06 22:58:57 EDT
(In reply to comment #8)
> The failing code has now be upgraded to support basic generics - the use of
> parameterized types and raw types *should* be ok... so this might be resolved in
> the next version of AJDT...  unfortunately without a simple testcase I can't
> confirm that right now...
Thank you for looking at this.

I created a simple testcase and attached it.  I discovered that the file where
the error was reported was *not* the file with the problem -- it just had the
bad luck of being the last file in the build path.

My test case has two java files, a parametized interface and a parametized type
implementing the interface.  If the parametized type does not implement the
interface, then there the error does not occur.
Comment 11 Andrew Clement CLA 2005-06-01 12:30:25 EDT
This appears fixed with the work I've done for bug 97763.

Without my changes (actually with the dev build 20050510144051), on compiling
the attached test program I was getting:

[error] can't find type test.TroubleInterface<java.lang.Object>


1 error

Now with my changes, I don't get any errors at all.

Waiting on a dev build to be uploaded now...
Comment 12 Andrew Clement CLA 2005-06-03 11:34:00 EDT
Fixed in latest dev build from http://eclipse.org/aspectj/downloads.php