Index: org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/GroovyProposal.java
===================================================================
--- org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/GroovyProposal.java	(revision 0)
+++ org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/GroovyProposal.java	(revision 0)
@@ -0,0 +1,101 @@
+package org.codehaus.groovy.eclipse.codeassist.completion;
+
+import org.codehaus.groovy.ast.ModuleNode;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+
+public class GroovyProposal implements ICompletionProposal {
+
+	protected String replacementString;
+	protected int replacementOffset;
+	protected int replacementLength;
+	protected int cursorPosition;
+	protected Image image;
+	protected String displayString;
+	protected IContextInformation contextInformation;
+	protected String additionalProposalInfo;
+
+	protected IFile file;
+	protected ModuleNode moduleNode;
+
+	protected GroovyProposal() {
+	}
+
+	/**
+	 * Creates a new completion proposal. All fields are initialized based on
+	 * the provided information.
+	 * 
+	 * @param replacementString
+	 *            the actual string to be inserted into the document
+	 * @param replacementOffset
+	 *            the offset of the text to be replaced
+	 * @param replacementLength
+	 *            the length of the text to be replaced
+	 * @param cursorPosition
+	 *            the position of the cursor following the insert relative to
+	 *            replacementOffset
+	 * @param image
+	 *            the image to display for this proposal
+	 * @param displayString
+	 *            the string to be displayed for the proposal
+	 * @param contextInformation
+	 *            the context information associated with this proposal
+	 * @param additionalProposalInfo
+	 *            the additional information associated with this proposal
+	 */
+	public GroovyProposal(String replacementString, int replacementOffset,
+			int replacementLength, int cursorPosition, Image image,
+			String displayString, IContextInformation contextInformation,
+			String additionalProposalInfo) {
+		Assert.isNotNull(replacementString);
+		Assert.isTrue(replacementOffset >= 0);
+		Assert.isTrue(replacementLength >= 0);
+		Assert.isTrue(cursorPosition >= 0);
+
+		this.replacementString = replacementString;
+		this.replacementOffset = replacementOffset;
+		this.replacementLength = replacementLength;
+		this.cursorPosition = cursorPosition;
+		this.image = image;
+		this.displayString = displayString;
+		this.contextInformation = contextInformation;
+		this.additionalProposalInfo = additionalProposalInfo;
+	}
+
+	public void apply(IDocument document) {
+		try {
+			document.replace(replacementOffset, replacementLength,
+					replacementString);
+		} catch (BadLocationException x) {
+			// ignore
+		}
+	}
+
+	public String getAdditionalProposalInfo() {
+		return additionalProposalInfo;
+	}
+
+	public IContextInformation getContextInformation() {
+		return contextInformation;
+	}
+
+	public String getDisplayString() {
+		if (displayString != null)
+			return displayString;
+		return replacementString;
+	}
+
+	public Image getImage() {
+		return image;
+	}
+
+	public Point getSelection(IDocument document) {
+		return new Point(replacementOffset + cursorPosition, 0);
+	}
+}
Index: org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/ImportedClassProcessor.groovy
===================================================================
--- org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/ImportedClassProcessor.groovy	(revision 10175)
+++ org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/ImportedClassProcessor.groovy	(working copy)
@@ -24,9 +24,6 @@
 import org.eclipse.jface.text.contentassist.IContextInformation
 import org.eclipse.jface.text.contentassist.IContextInformationValidator
 
-// FUTURE: emp - auto import will need to ignore these packages:
-// static final defaultImports = ['java.lang', 'java.util', 'java.io', 'java.net', 'groovy.lang', 'groovy.util'] as Set
-
 /**
  * Completion processor for adding imported classes.
  * 
@@ -98,17 +95,13 @@
 		// Check the current imports for the package name and then if not found, make a proposal that would insert
 		// the import when the proposal is applied.
 		
+		def file = getCurrentFile()
+		def moduleNode = getModuleNodeForFile(file)
+
 		def proposals = []
 		
 		classNames.each { name ->
-			def ix = name.lastIndexOf('.')
-			def packageName = ix != -1 ? name[0..<ix] : "default package"
-			def simpleName = ix != -1 ? name[(ix+1)..<name.length()] : name
-			def displayName = "$simpleName - $packageName"
-			def replaceName = simpleName
-			
-			proposals << new CompletionProposal(replaceName, offset, replaceLength, replaceName.length(), 
-					JavaPluginImages.get(JavaPluginImages.IMG_OBJS_CLASS), displayName, null, null);
+			proposals << new ImportProposal(name, offset, replaceLength, file, moduleNode);
 		}
 	
 		return proposals
Index: org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/ImportProposal.groovy
===================================================================
--- org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/ImportProposal.groovy	(revision 0)
+++ org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completion/ImportProposal.groovy	(revision 0)
@@ -0,0 +1,93 @@
+package org.codehaus.groovy.eclipse.codeassist.completion;
+
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ModuleNode;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.internal.ui.JavaPluginImages;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.FindReplaceDocumentAdapter;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.swt.graphics.Image;
+
+class ImportProposal extends GroovyProposal {
+	
+    static final defaultImports = ['java.lang', 'java.util', 'java.io', 'java.net', 'groovy.lang', 'groovy.util'] as Set
+	def className
+	def packageName
+	def simpleName
+	
+	ImportProposal(String name, int replacementOffset, int replacementLength, IFile file, ModuleNode moduleNode) {
+		this.className = name
+		
+		def ix = name.lastIndexOf('.')
+		packageName = ix != -1 ? name[0..<ix] : "default package"
+		simpleName = ix != -1 ? name[(ix+1)..<name.length()] : name
+		
+		this.replacementString = simpleName
+		this.replacementOffset = replacementOffset
+		this.replacementLength = replacementLength
+		this.cursorPosition = simpleName.length()
+		this.image = JavaPluginImages.get(JavaPluginImages.IMG_OBJS_CLASS)
+		this.displayString = "$simpleName - $packageName"
+		
+		this.file = file
+		this.moduleNode = moduleNode 
+	}
+
+	void apply(IDocument document) {
+		super.apply(document);
+		
+		if (!defaultImports.contains(packageName)) {
+			int line = getImportLocation(document)
+			int offset = document.getLineOffset(line)
+			String importLine = "import " + className + document.legalLineDelimiters[0]
+			document.replace(offset, 0, importLine)
+			cursorPosition += importLine.length()
+		}
+	}
+	
+	private int getImportLocation(IDocument document) {
+		int line = 0;
+		
+		// an alternative implementation would be for the PartitionScanner to
+		// give us an import partition
+
+		/* this doesn't work because the line numbers aren't kept in the AST for some reason
+		if (moduleNode.imports.isEmpty()) {
+			if (moduleNode.classes.isEmpty()) {
+				line = moduleNode.statementBlock.lineNumber - 1
+			} else {
+				line = moduleNode.classes[0].lineNumber - 1
+			}
+		} else {
+			line = moduleNode.imports[moduleNode.imports.size() - 1].lastLineNumber
+		}
+		if (line == -1) {
+			line = 0
+		}
+		*/
+		
+		if (line == 0) {
+			// imports must be after the package declaration if one exists
+			def finder = new FindReplaceDocumentAdapter(document)
+			def region = finder.find(0, "^package ", true, true, false, true)
+			if (region != null) {
+				line = document.getLineOfOffset(region.offset) + 1
+				
+				def lineValue = { return document.get(document.getLineOffset(line), document.getLineLength(line)) }
+				if (!document.legalLineDelimiters.toList().contains(lineValue())) {
+					// insert a blank line if one does not exist
+					document.replace(document.getLineOffset(line), 0, document.legalLineDelimiters[0])
+					cursorPosition += document.legalLineDelimiters[0].length()
+				}
+				
+				line++
+				while (lineValue().startsWith("import ")) {
+					line++
+				}
+			}
+		}
+
+		return line
+	}
+}

