/******************************************************************************* * Copyright (c) 2007 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and implementation *******************************************************************************/ package org.eclipse.imp.model.internal; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.imp.core.ErrorHandler; import org.eclipse.imp.language.Language; import org.eclipse.imp.language.LanguageRegistry; import org.eclipse.imp.language.ServiceFactory; import org.eclipse.imp.model.ICompilationUnit; import org.eclipse.imp.model.ISourceEntity; import org.eclipse.imp.model.ISourceFolder; import org.eclipse.imp.model.ISourceProject; import org.eclipse.imp.model.IWorkspaceModel; import org.eclipse.imp.model.ModelFactory; import org.eclipse.imp.model.ModelFactory.ModelException; import org.eclipse.imp.parser.IMessageHandler; import org.eclipse.imp.parser.IParseController; import org.eclipse.imp.runtime.RuntimePlugin; import org.eclipse.jface.text.IDocument; import org.eclipse.ui.editors.text.TextFileDocumentProvider; public class CompilationUnitRef implements ICompilationUnit { /** * The containing ISourceProject. May be null if the associated path is * workspace-absolute. */ final ISourceProject fProject; /** * Path may be either workspace-absolute or project-relative. If * workspace-absolute, fProject will be null. */ final IPath fPath; // possibly src-folder-relative? // TODO This should be created lazily private IParseController fParseCtrlr; /** * @param path * may be either workspace-absolute or project-relative * @param proj * may be null if path is workspace-absolute */ public CompilationUnitRef(IPath path, ISourceProject proj) { fProject= proj; fPath= path; } /** * @return the associated ISourceProject. May be null if the unit's path is * workspace-absolute. */ public ISourceProject getProject() { return fProject; } /** * @return the associated IPath, which may be either workspace-absolute or * project-relative */ public IPath getPath() { return fPath; } public String getName() { return fPath.lastSegment(); // if (fPath.isAbsolute()) // return fPath.toPortableString(); // return fProject.getRawProject().getName() + ":" + fPath; } public ISourceEntity getParent() { IContainer parent= (IContainer) fProject.getRawProject().findMember( fPath.removeLastSegments(1)); try { return ModelFactory.open(parent); } catch (ModelException e) { RuntimePlugin.getInstance().logException( "Error obtaining parent of " + getName(), e); return null; } } public ISourceEntity getAncestor(Class ofType) { if (ofType == ICompilationUnit.class) { return this; } else if (ofType == ISourceProject.class) { return fProject; } else if (ofType == IWorkspaceModel.class) { return ModelFactory.getModelRoot(); } else if (ofType == ISourceFolder.class) { return getParent(); } return null; } public IResource getResource() { return getFile(); } public IFile getFile() { if (fPath.getDevice() != null && fPath.getDevice().length() > 0) return null; // This is a filesystem-absolute path; can't build // an IFile for that if (fPath.isAbsolute()) return fProject.getRawProject().getWorkspace().getRoot().getFile( fPath); return fProject.getRawProject().getFile(fPath); } public Object getAST(IMessageHandler msgHandler, IProgressMonitor monitor) { IFile file= getFile(); TextFileDocumentProvider tfdp= new TextFileDocumentProvider(); IDocument doc= (file != null) ? tfdp.getDocument(file) : null; // if (file == null) // return null; if (fParseCtrlr == null) { Language lang= LanguageRegistry.findLanguage(fPath, doc); fParseCtrlr= ServiceFactory.getInstance().getParseController(lang); } IPath projRelPath= fPath.isAbsolute() ? fPath.removeFirstSegments(1) : fPath; fParseCtrlr.initialize(projRelPath, fProject, msgHandler); return fParseCtrlr.parse(getSource(), monitor); } public String getSource() { String absPath= (fPath.getDevice() != null) ? fPath.toOSString() : (fPath.isAbsolute() ? ResourcesPlugin.getWorkspace() .getRoot().getLocation().append(fPath).toOSString() : fProject.getRawProject().getLocation().append(fPath) .toOSString()); File inFile= new File(absPath); if (!inFile.exists() || !inFile.canRead()) { throw new IllegalArgumentException( "CompilationUnitRef.getSource(): file does not exist or cannot be read: " + this); } // Get a buffered reader for the input file FileReader fileReader= null; long fileLen= inFile.length(); try { fileReader= new FileReader(inFile); char[] buffer= new char[(int) fileLen]; fileReader.read(buffer); return new String(buffer); } catch (FileNotFoundException e) { ErrorHandler .reportError("CompilationUnitRef.getSource(): file not found: " + this); return null; } catch (IOException e) { ErrorHandler .reportError("CompilationUnitRef.getSource(): cannot read file: " + this); return null; } } public void commit(IProgressMonitor mon) { // do nothing } @Override public boolean equals(Object obj) { if (!(obj instanceof CompilationUnitRef)) return false; CompilationUnitRef other= (CompilationUnitRef) obj; return fProject.equals(other.fProject) && fPath.equals(other.fPath); } @Override public int hashCode() { int result= 4831; result= result * 4933 + (fProject != null ? fProject.hashCode() : 13); result= result * 1627 + fPath.hashCode(); return result; } public String toString() { return "<compilation unit " + getPath().toPortableString() + ">"; } }