diff --git a/core/org.eclipse.cdt.core/.cvsignore b/core/org.eclipse.cdt.core/.cvsignore new file mode 100644 index 00000000000..ba077a4031a --- /dev/null +++ b/core/org.eclipse.cdt.core/.cvsignore @@ -0,0 +1 @@ +bin diff --git a/core/org.eclipse.cdt.core/.project b/core/org.eclipse.cdt.core/.project new file mode 100644 index 00000000000..95eceb11fac --- /dev/null +++ b/core/org.eclipse.cdt.core/.project @@ -0,0 +1,28 @@ + + + org.eclipse.cdt.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/core/org.eclipse.cdt.core/build.properties b/core/org.eclipse.cdt.core/build.properties new file mode 100644 index 00000000000..14f60351eec --- /dev/null +++ b/core/org.eclipse.cdt.core/build.properties @@ -0,0 +1,10 @@ +################################################ +# +# (c) Copyright QNX Software Systems Ltd. 2002. +# All Rights Reserved. +# +################################################ +source.cdt.jar = builder,\ + index,\ + model,\ + src diff --git a/core/org.eclipse.cdt.core/build.xml b/core/org.eclipse.cdt.core/build.xml new file mode 100644 index 00000000000..0a669b719da --- /dev/null +++ b/core/org.eclipse.cdt.core/build.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.core/builder/org/eclipse/cdt/core/builder/BuilderModel.java b/core/org.eclipse.cdt.core/builder/org/eclipse/cdt/core/builder/BuilderModel.java new file mode 100644 index 00000000000..ca9c3571c39 --- /dev/null +++ b/core/org.eclipse.cdt.core/builder/org/eclipse/cdt/core/builder/BuilderModel.java @@ -0,0 +1,113 @@ +package org.eclipse.cdt.core.builder; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; + +public class BuilderModel { + + private static BuilderModel buildModel = null; + + public final static String PLUGIN_ID = "org.eclipse.cdt.core"; + public final static String BUILDER_NAME = "cbuilder"; + public final static String BUILDER_ID = PLUGIN_ID + "." + BUILDER_NAME; + + public static String getBuilderName () { + return BUILDER_NAME; + } + + public static String getBuilderId () { + return BUILDER_ID; + } + + public IBuildPath getBuildPath(IProject project) { + return null; + } + + public void setBuildPath(IProject project, IBuildPath bp) { + } + + public void addBuildListener () { + } + + public void removeBuildListener() { + } + + public void build(IProject project, IPath workingDir, String[] args) { + } + + /** + * Adds default C Builder. + */ + public void addCToBuildSpec(IProject project) throws CoreException { + addToBuildSpec(project, getBuilderId()); + } + + /** + * Adds a builder to the build spec for the given project. + */ + public void addToBuildSpec(IProject project, String builderID) throws CoreException { + IProjectDescription description = project.getDescription(); + ICommand[] commands = description.getBuildSpec(); + ICommand command = null; + for (int i = 0; i < commands.length; i++) { + if (commands[i].getBuilderName().equals(builderID)) { + command = commands[i]; + break; + } + } + if (command == null) { + command = description.newCommand(); + command.setBuilderName(builderID); + + // Add a build spec before other builders (1FWJK7I) + ICommand[] newCommands = new ICommand[commands.length + 1]; + System.arraycopy(commands, 0, newCommands, 1, commands.length); + newCommands[0] = command; + // Commit the spec change into the project + description.setBuildSpec(newCommands); + project.setDescription(description, null); + } + } + + /** + * Removes the default C Builder. + */ + public void removeCFromBuildSpec(IProject project) throws CoreException { + removeFromBuildSpec(project, getBuilderId()); + } + + /** + * Removes the given builder from the build spec for the given project. + */ + public void removeFromBuildSpec(IProject project, String builderID) throws CoreException { + IProjectDescription description = project.getDescription(); + ICommand[] commands = description.getBuildSpec(); + for (int i = 0; i < commands.length; ++i) { + if (commands[i].getBuilderName().equals(builderID)) { + ICommand[] newCommands = new ICommand[commands.length - 1]; + System.arraycopy(commands, 0, newCommands, 0, i); + System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1); + description.setBuildSpec(newCommands); + project.setDescription(description, null); + } + } + } + + private BuilderModel() { + } + + public static BuilderModel getDefault() { + if (buildModel == null) { + buildModel = new BuilderModel(); + } + return buildModel; + } +} diff --git a/core/org.eclipse.cdt.core/builder/org/eclipse/cdt/core/builder/IBuildPath.java b/core/org.eclipse.cdt.core/builder/org/eclipse/cdt/core/builder/IBuildPath.java new file mode 100644 index 00000000000..024d0e89b69 --- /dev/null +++ b/core/org.eclipse.cdt.core/builder/org/eclipse/cdt/core/builder/IBuildPath.java @@ -0,0 +1,91 @@ +package org.eclipse.cdt.core.builder; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ +import org.eclipse.core.runtime.IPath; + +/** + * A BuildPath can contain the following: + */ + +public interface IBuildPath { + + public String[] getCPPOpts(); + public String[] getCPPFlags(); + public void setCPP(IPath p); + public void setCPPOpts(String[] s); + public void setCPPFlags(String[] s); + + public IPath getCXX(); + public String[] getCXXOPT(); + public String[] getCXXFlags(); + public void setCXX(IPath p); + public void setCXXOpts(String[] s); + public void setCXXFlags(String[] s); + + public IPath getCC(); + public String[] getCFLAGS(); + public String[] getCOpts(); + public void setCFLAGS(String[] s); + public void setCOpts(String[] s); + public void setCC(IPath p); + + public IPath getAS(); + public String[] getASFlags(); + public String[] getASOpts(); + public void getAS(IPath p); + public void getASOpts(String[] s); + public void getASFlags(String[] s); + + public IPath getLD(); + public String[] getLDOpts(); + public String[] getLDFlags(); + public void setLD(IPath p); + public void setLDOpts(String[] s); + public void setLDFlags(String[] s); + + public IPath getAR(); + public String[] getARFlags(); + public String[] getAROpts(); + public void setAR(IPath p); + public void setAROpts(String[] s); + public void setARFlags(String[] s); + + public IPath[] getIncVPath(); + public void setIncVPath(IPath[] p); + + public IPath[] getLibs(); + public void setLibs(IPath[] p); + + public IPath[] getLibVPath(); + public void setLibVPath(IPath[] p); + + public IPath[] getSRCVPath(); + public void setSRCVPath(IPath[] p); +} diff --git a/core/org.eclipse.cdt.core/icons/full/clcl16/alphab_sort_co.gif b/core/org.eclipse.cdt.core/icons/full/clcl16/alphab_sort_co.gif new file mode 100644 index 00000000000..6d772441d0d Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/clcl16/alphab_sort_co.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/clcl16/clear_co.gif b/core/org.eclipse.cdt.core/icons/full/clcl16/clear_co.gif new file mode 100644 index 00000000000..255832653fd Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/clcl16/clear_co.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/clcl16/open_incl.gif b/core/org.eclipse.cdt.core/icons/full/clcl16/open_incl.gif new file mode 100644 index 00000000000..58b9a012e89 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/clcl16/open_incl.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/clcl16/shift_l_edit.gif b/core/org.eclipse.cdt.core/icons/full/clcl16/shift_l_edit.gif new file mode 100644 index 00000000000..2700d541ecf Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/clcl16/shift_l_edit.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/clcl16/shift_r_edit.gif b/core/org.eclipse.cdt.core/icons/full/clcl16/shift_r_edit.gif new file mode 100644 index 00000000000..fed137329e7 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/clcl16/shift_r_edit.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/ctool16/newcprj_wiz.gif b/core/org.eclipse.cdt.core/icons/full/ctool16/newcprj_wiz.gif new file mode 100644 index 00000000000..812cf458709 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/ctool16/newcprj_wiz.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/ctool16/newfile_wiz.gif b/core/org.eclipse.cdt.core/icons/full/ctool16/newfile_wiz.gif new file mode 100644 index 00000000000..6baa03787f4 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/ctool16/newfile_wiz.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/cview16/buildconsole.gif b/core/org.eclipse.cdt.core/icons/full/cview16/buildconsole.gif new file mode 100644 index 00000000000..4723724a209 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/cview16/buildconsole.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/cview16/c_pers.gif b/core/org.eclipse.cdt.core/icons/full/cview16/c_pers.gif new file mode 100644 index 00000000000..86316d592ee Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/cview16/c_pers.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/dlcl16/alphab_sort_co.gif b/core/org.eclipse.cdt.core/icons/full/dlcl16/alphab_sort_co.gif new file mode 100644 index 00000000000..62a8fdb555b Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/dlcl16/alphab_sort_co.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/dlcl16/clear_co.gif b/core/org.eclipse.cdt.core/icons/full/dlcl16/clear_co.gif new file mode 100644 index 00000000000..d873c49b8a0 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/dlcl16/clear_co.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/dlcl16/open_incl.gif b/core/org.eclipse.cdt.core/icons/full/dlcl16/open_incl.gif new file mode 100644 index 00000000000..9bdd658229f Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/dlcl16/open_incl.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/dlcl16/shift_l_edit.gif b/core/org.eclipse.cdt.core/icons/full/dlcl16/shift_l_edit.gif new file mode 100644 index 00000000000..a93966ed990 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/dlcl16/shift_l_edit.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/dlcl16/shift_r_edit.gif b/core/org.eclipse.cdt.core/icons/full/dlcl16/shift_r_edit.gif new file mode 100644 index 00000000000..c1254afc730 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/dlcl16/shift_r_edit.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/dtool16/newcprj_wiz.gif b/core/org.eclipse.cdt.core/icons/full/dtool16/newcprj_wiz.gif new file mode 100644 index 00000000000..82450711805 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/dtool16/newcprj_wiz.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/dtool16/newfile_wiz.gif b/core/org.eclipse.cdt.core/icons/full/dtool16/newfile_wiz.gif new file mode 100644 index 00000000000..c931715bb32 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/dtool16/newfile_wiz.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/elcl16/alphab_sort_co.gif b/core/org.eclipse.cdt.core/icons/full/elcl16/alphab_sort_co.gif new file mode 100644 index 00000000000..9d38f6dff8a Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/elcl16/alphab_sort_co.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/elcl16/clear_co.gif b/core/org.eclipse.cdt.core/icons/full/elcl16/clear_co.gif new file mode 100644 index 00000000000..6faf8d66fef Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/elcl16/clear_co.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/elcl16/open_incl.gif b/core/org.eclipse.cdt.core/icons/full/elcl16/open_incl.gif new file mode 100644 index 00000000000..aec95f8fbcc Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/elcl16/open_incl.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/elcl16/shift_l_edit.gif b/core/org.eclipse.cdt.core/icons/full/elcl16/shift_l_edit.gif new file mode 100644 index 00000000000..fe7b3111b11 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/elcl16/shift_l_edit.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/elcl16/shift_r_edit.gif b/core/org.eclipse.cdt.core/icons/full/elcl16/shift_r_edit.gif new file mode 100644 index 00000000000..e0f2a56933d Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/elcl16/shift_r_edit.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/etool16/newcprj_wiz.gif b/core/org.eclipse.cdt.core/icons/full/etool16/newcprj_wiz.gif new file mode 100644 index 00000000000..5f7c6a973f8 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/etool16/newcprj_wiz.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/etool16/newfile_wiz.gif b/core/org.eclipse.cdt.core/icons/full/etool16/newfile_wiz.gif new file mode 100644 index 00000000000..f2fe6e1d036 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/etool16/newfile_wiz.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/eview16/buildconsole.gif b/core/org.eclipse.cdt.core/icons/full/eview16/buildconsole.gif new file mode 100644 index 00000000000..56d14e449eb Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/eview16/buildconsole.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/eview16/c_pers.gif b/core/org.eclipse.cdt.core/icons/full/eview16/c_pers.gif new file mode 100644 index 00000000000..655cd2f4c21 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/eview16/c_pers.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/obj16/c_file_obj.gif b/core/org.eclipse.cdt.core/icons/full/obj16/c_file_obj.gif new file mode 100644 index 00000000000..1bb68c2d649 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/obj16/c_file_obj.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/obj16/class_obj.gif b/core/org.eclipse.cdt.core/icons/full/obj16/class_obj.gif new file mode 100644 index 00000000000..a4a14864987 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/obj16/class_obj.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/obj16/define_obj.gif b/core/org.eclipse.cdt.core/icons/full/obj16/define_obj.gif new file mode 100644 index 00000000000..b3ddb5deebc Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/obj16/define_obj.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/obj16/field_obj.gif b/core/org.eclipse.cdt.core/icons/full/obj16/field_obj.gif new file mode 100644 index 00000000000..19d27defb62 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/obj16/field_obj.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/obj16/function_obj.gif b/core/org.eclipse.cdt.core/icons/full/obj16/function_obj.gif new file mode 100644 index 00000000000..18103b11fc7 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/obj16/function_obj.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/obj16/include_obj.gif b/core/org.eclipse.cdt.core/icons/full/obj16/include_obj.gif new file mode 100644 index 00000000000..2cc5866a64c Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/obj16/include_obj.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/obj16/struct_obj.gif b/core/org.eclipse.cdt.core/icons/full/obj16/struct_obj.gif new file mode 100644 index 00000000000..cb2869f2488 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/obj16/struct_obj.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/obj16/union_obj.gif b/core/org.eclipse.cdt.core/icons/full/obj16/union_obj.gif new file mode 100644 index 00000000000..b8405d54bb4 Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/obj16/union_obj.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/ovr16/c_ovr.gif b/core/org.eclipse.cdt.core/icons/full/ovr16/c_ovr.gif new file mode 100644 index 00000000000..bec7ac2faef Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/ovr16/c_ovr.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/wizban/c_app_wiz.gif b/core/org.eclipse.cdt.core/icons/full/wizban/c_app_wiz.gif new file mode 100644 index 00000000000..60ccf9c7c6a Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/wizban/c_app_wiz.gif differ diff --git a/core/org.eclipse.cdt.core/icons/full/wizban/newcprj_wiz.gif b/core/org.eclipse.cdt.core/icons/full/wizban/newcprj_wiz.gif new file mode 100644 index 00000000000..60ccf9c7c6a Binary files /dev/null and b/core/org.eclipse.cdt.core/icons/full/wizban/newcprj_wiz.gif differ diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/ITagEntry.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/ITagEntry.java new file mode 100644 index 00000000000..1a89c75b46e --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/ITagEntry.java @@ -0,0 +1,78 @@ +package org.eclipse.cdt.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IFile; + + +public interface ITagEntry { + + /** + * Name of tag. + */ + public String getTagName(); + + /** + * Path of source file containing definition of tag. + */ + public String getFileName(); + + /** + * IFile of source file containing definition of tag. + */ + public IFile getIFile(); + + /** + * Address for locating tag in source file + * (may be null if not present). + */ + public String getPattern(); + + /** + * line number in source file of tag definition + * (may be zero if not known). + */ + public int getLineNumber(); + + /** + * Kind of tag. + */ + public int getKind(); + + /** + * Language of the file. + */ + public String getLanguage(); + + /** + * Is tag of file-limited scope? + */ + public boolean hasFileScope(); + + /** + * Return base classes. + */ + public String[] getInherits(); + + /** + * Access Control of structure/class/union members. + */ + public int getAccessControl(); + + // implementation: + public int getImplementation(); + + /** + * Class name of the tag if a member, + * null if not a member of a struct/class/union. + */ + public String getClassName(); + + /** + * Return the original tag line. + */ + public String getLine(); +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/IndexModel.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/IndexModel.java new file mode 100644 index 00000000000..919fc09cd53 --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/IndexModel.java @@ -0,0 +1,62 @@ +package org.eclipse.cdt.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +import org.eclipse.cdt.internal.core.index.IndexManager; + +public class IndexModel { + + static IndexModel indexModel = null; + static IndexManager manager = null; + + /** + * Search Project for tag symbol. + */ + public ITagEntry[] query (IProject project, String tag) { + return manager.query(project, tag, true, false); + } + + /** + * Search Project for tag symbol. + */ + public ITagEntry[] query (IProject project, String tag, boolean ignoreCase, boolean exactMatch) { + return manager.query(project, tag, ignoreCase, exactMatch); + } + + /** + * Add a resource to be index. Containers(Folder, projects) + * resources are recusively search for C Files as define by + * CoreModel.isTranslationUnit(). + */ + public void addResource(IResource resource) { + manager.addResource(resource); + } + + /** + * Add all the C files recurively going to all projects + * identified as C Projects by CoreModel. + */ + public void addAll () { + manager.addAll(); + } + + /** + * Initialize default index Model. + */ + public static IndexModel getDefault() { + if (indexModel == null) { + indexModel = new IndexModel(); + manager = IndexManager.getDefault(); + } + return indexModel; + } + + private IndexModel () { + } +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/TagFlags.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/TagFlags.java new file mode 100644 index 00000000000..ef9fed96bab --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/core/index/TagFlags.java @@ -0,0 +1,179 @@ +package org.eclipse.cdt.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + + +public class TagFlags { + + public final static int T_UNKNOWN = 0; + public final static int T_CLASS = 1; + public final static int T_MACRO = 2; + public final static int T_ENUMERATOR = 3; + public final static int T_FUNCTION = 4; + public final static int T_ENUM = 5; + public final static int T_MEMBER = 6; + public final static int T_NAMESPACE = 7; + public final static int T_PROTOTYPE = 8; + public final static int T_STRUCT = 9; + public final static int T_TYPEDEF = 10; + public final static int T_UNION = 11; + public final static int T_VARIABLE = 12; + public final static int T_EXTERNVAR = 13; + + public final static int T_PRIVATE = 14; + public final static int T_PROTECTED = 15; + public final static int T_PUBLIC = 16; + public final static int T_FRIEND = 17; + public final static int T_VIRTUAL = 18; + public final static int T_ABSTRACT = 19; + + private TagFlags() { + } + + public static boolean isUnknown(int k) { + return k == T_UNKNOWN; + } + + public static boolean isClass(int k) { + return k == T_CLASS; + } + + public static boolean isMacro(int k) { + return k == T_MACRO; + } + + public static boolean isEnumerator(int k) { + return k == T_ENUMERATOR; + } + + public static boolean isFunction(int k) { + return k == T_FUNCTION; + } + + public static boolean isEnum(int k) { + return k == T_ENUM; + } + + public static boolean isMember(int k) { + return k == T_MEMBER; + } + + public static boolean isNamespace(int k) { + return k == T_NAMESPACE; + } + + public static boolean isPrototype(int k) { + return k == T_PROTOTYPE; + } + + public static boolean isStruct(int k) { + return k == T_STRUCT; + } + + public static boolean isTypedef(int k) { + return k == T_TYPEDEF; + } + + public static boolean isUnion(int k) { + return k == T_UNION; + } + + public static boolean isVariable(int k) { + return k == T_VARIABLE; + } + + public static boolean isExternVar(int k) { + return k == T_EXTERNVAR; + } + + public static int value(String flag) { + if (flag == null) { + return T_UNKNOWN; + } else if (flag.equals("class")) { + return T_CLASS; + } else if (flag.equals("macro")) { + return T_MACRO; + } else if (flag.equals("enumerator")) { + return T_ENUMERATOR; + } else if (flag.equals("function")) { + return T_FUNCTION; + } else if (flag.equals("enum")) { + return T_ENUM; + } else if (flag.equals("member")) { + return T_MEMBER; + } else if (flag.equals("namespace")) { + return T_NAMESPACE; + } else if (flag.equals("prototype")) { + return T_PROTOTYPE; + } else if (flag.equals("struct")) { + return T_STRUCT; + } else if (flag.equals("typedef")) { + return T_TYPEDEF; + } else if (flag.equals("union")) { + return T_UNION; + } else if (flag.equals("variable")) { + return T_VARIABLE; + } else if (flag.equals("externvar")) { + return T_EXTERNVAR; + } else if (flag.equals("public")) { + return T_PUBLIC; + } else if (flag.equals("private")) { + return T_PRIVATE; + } else if (flag.equals("protected")) { + return T_PROTECTED; + } else if (flag.equals("virtual")) { + return T_VIRTUAL; + } else if (flag.equals("abstract")) { + return T_ABSTRACT; + } else if (flag.equals("friend")) { + return T_FRIEND; + } + return T_UNKNOWN; + } + + public static String value(int flag) { + if (flag == T_CLASS) { + return "class"; + } else if (flag == T_MACRO) { + return "macro"; + } else if (flag == T_ENUMERATOR) { + return "enumerator"; + } else if (flag == T_FUNCTION) { + return "function"; + } else if (flag == T_ENUM) { + return "enum"; + } else if (flag == T_MEMBER) { + return "member"; + } else if (flag == T_NAMESPACE) { + return "namespace"; + } else if (flag == T_PROTOTYPE) { + return "prototype"; + } else if (flag == T_STRUCT) { + return "struct"; + } else if (flag == T_TYPEDEF) { + return "typedef"; + } else if (flag == T_UNION) { + return "union"; + } else if (flag == T_VARIABLE) { + return "variable"; + } else if (flag == T_EXTERNVAR) { + return "externvar"; + } else if (flag == T_PUBLIC) { + return "public"; + } else if (flag == T_PRIVATE) { + return "private"; + } else if (flag == T_PROTECTED) { + return "protected"; + } else if (flag == T_VIRTUAL) { + return "virtual"; + } else if (flag == T_ABSTRACT) { + return "abstract"; + } else if (flag == T_FRIEND) { + return "friend"; + } + return null; + } +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsCmd.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsCmd.java new file mode 100644 index 00000000000..57d1dfec06f --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsCmd.java @@ -0,0 +1,83 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.resources.IFile; +import org.eclipse.cdt.core.index.ITagEntry; +import org.eclipse.cdt.utils.spawner.ProcessFactory; + +public class CTagsCmd { + + public CTagsCmd() { + } + + private void process(String filename, List list, IFile file) throws IOException { + + BufferedReader stdout; + + String[] args = {"ctags", "--excmd=pattern", "--format=2", + "--if0=yes", "--sort=no", "--extra=q", + "--fields=aiKlmnsz", "--line-directives=yes", + "--sort=no", "--kind-long", "--c-types=cdefgmnpstuvx", + "-f", "-", filename}; + + //Process ctags = Runtime.getRuntime().exec(args); + Process ctags = ProcessFactory.getFactory().exec(args); + //stdin = new BufferedWriter(new OutputStreamWriter(ctags.getOutputStream())); + stdout = new BufferedReader(new InputStreamReader(ctags.getInputStream())); + + //System.out.println("Processing"); + String line; + try { + while ((line = stdout.readLine()) != null) { + //System.out.println("ProcessingLine " + line); + CTagsEntry entry = new CTagsEntry(line, file); + list.add(entry); + } + } catch (IOException e) { + //e.printStackTrace(); + } + + // Force an explicit close even if + // we call destroy() + try { + stdout.close(); + ctags.getOutputStream().close(); + ctags.getErrorStream().close(); + } catch (IOException e) { + } + ctags.destroy(); + } + + public ITagEntry[] getTagEntries(IFile file, String filename) throws IOException { + List list = new LinkedList(); + process(filename, list, file); + return (ITagEntry[])list.toArray(new ITagEntry[0]); + } + + public static void main(String[] args) { + try { + CTagsCmd cmd = new CTagsCmd(); + ITagEntry[] entries = cmd.getTagEntries(null, args[0]); + for (int i = 0; i < entries.length; i++) { + if (entries[i] instanceof CTagsEntry) { + CTagsEntry entry = (CTagsEntry)entries[i]; + System.out.println(entry.getLine() + "\n"); + entry.print(); + System.out.println("\n"); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsEntry.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsEntry.java new file mode 100644 index 00000000000..8101d3a1f36 --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsEntry.java @@ -0,0 +1,272 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.core.resources.IFile; +import org.eclipse.cdt.core.index.ITagEntry; +import org.eclipse.cdt.core.index.TagFlags; + +public class CTagsEntry implements ITagEntry { + + final static String TAB_SEPARATOR = "\t"; + final static String PATTERN_SEPARATOR = ";\""; + final static String LANGUAGE = "language"; + final static String KIND = "kind"; + final static String LINE = "line"; + final static String FILE = "file"; + final static String INHERITS = "inherits"; + final static String ACCESS = "access"; + final static String IMPLEMENTATION = "implementation"; + final static String CLASS = "class"; + + final String[] NONE = new String[0]; + + String tagName; + + /* Path of source file containing definition of tag. */ + String fileName; + + /* IFile of parsed file */ + IFile file; + + /* pattern for locating source line + * (may be NULL if not present) */ + String pattern; + + int lineNumber; + + /* Miscellaneous extension fields */ + HashMap tagExtensionField; + + String line; + + public CTagsEntry(String line, IFile file) { + this.line = line; + this.file = file; + tagName = ""; + fileName =""; + pattern = null; + lineNumber = 0; + tagExtensionField = new HashMap(); + parse(); + } + + void parse () { + String delim = TAB_SEPARATOR; + StringTokenizer st = new StringTokenizer(line, delim); + for (int state = 0; st.hasMoreTokens(); state++) { + String token = st.nextToken(delim); + switch (state) { + case 0: // TAG_NAME: + tagName = token; + break; + + case 1: // FILE_NAME: + fileName = token; + delim = PATTERN_SEPARATOR; + break; + + case 2: // PATTERN; + try { + String sub = token.substring(1); + if (Character.isDigit(sub.charAt(0))) { + lineNumber = Integer.parseInt(sub); + } else { + // Filter out the delimiters + int i = sub.indexOf("/^"); + int j = sub.lastIndexOf("$/"); + try { + if(i >= 0 && j >= 0 ) { + sub = sub.substring(i + 2, j); + } else if(i >= 0) { + sub = sub.substring(i + 2, sub.length()-1); + } + } catch (Exception e) {} + pattern = sub; + } + } catch (NumberFormatException e) { + //e.printStackTrace(); + } catch (IndexOutOfBoundsException e) { + //e.printStackTrace(); + } + delim = TAB_SEPARATOR; + break; + + default: // EXTENSION_FIELDS: + int i = token.indexOf(':'); + if (i != -1) { + String key = token.substring(0, i); + String value = token.substring(i + 1); + tagExtensionField.put(key, value); + } + break; + } + } + } + + public String getTagName () { + return tagName; + } + + public String getFileName() { + return fileName; + } + public IFile getIFile() { + return file; + } + + public String getPattern() { + return pattern; + } + + // line: + public int getLineNumber() { + try { + String sub = (String)tagExtensionField.get(LINE); + if (sub != null) { + lineNumber = Integer.parseInt(sub); + } + } catch (NumberFormatException e) { + //System.out.println(e); + } + return lineNumber; + } + + // kind: + public int getKind() { + String kind = (String)tagExtensionField.get(KIND); + return TagFlags.value(kind); + } + + // language: + public String getLanguage() { + return (String)tagExtensionField.get(LANGUAGE); + } + + // Implementation: + public int getImplementation() { + String impl = (String)tagExtensionField.get(IMPLEMENTATION); + return TagFlags.value(impl); + } + + // Class: + public String getClassName() { + return (String)tagExtensionField.get(CLASS); + } + + // file: + public boolean hasFileScope() { + return (tagExtensionField.get(FILE) != null); + } + + // inherits: + public String[] getInherits() { + String base = (String)tagExtensionField.get(INHERITS); + if (base != null) { + StringTokenizer st = new StringTokenizer(base, ","); + List list = new ArrayList(); + while (st.hasMoreTokens()) { + list.add(st.nextToken()); + } + return (String[])list.toArray(new String[0]); + } + return NONE; + } + + // access: + public int getAccessControl() { + String access = (String)tagExtensionField.get(ACCESS); + return TagFlags.value(access); + } + + public String getLine() { + return line; + } + + public static String makeTagLine(ITagEntry tagEntry) { + StringBuffer buffer = new StringBuffer(); + buffer.append(tagEntry.getTagName()); + buffer.append("\t"); + buffer.append(tagEntry.getFileName()); + buffer.append("\t"); + String pat = tagEntry.getPattern(); + if (pat != null) { + buffer.append(pat); + } else { + buffer.append(tagEntry.getLineNumber()); + } + buffer.append(";\""); + buffer.append("\t"); + + String kind = TagFlags.value(tagEntry.getKind()); + if (kind != null) { + buffer.append(KIND + ":" + tagEntry.getKind()); + buffer.append("\t"); + } + + String lang = tagEntry.getLanguage(); + if (lang != null) { + buffer.append(LANGUAGE + ":" + tagEntry.getLanguage()); + buffer.append("\t"); + } + + if (tagEntry.hasFileScope()) { + buffer.append(FILE + ":"); + buffer.append("\t"); + } + + String[] inherits = tagEntry.getInherits(); + for (int i = 0; i < inherits.length; i++) { + if (i == 0) { + buffer.append(INHERITS + ":"); + } else { + buffer.append(","); + } + buffer.append(inherits[i]); + } + + String access = TagFlags.value(tagEntry.getAccessControl()); + if (access != null) { + buffer.append(ACCESS + ":" + access); + buffer.append("\t"); + } + + String impl = TagFlags.value(tagEntry.getImplementation()); + if (impl != null) { + buffer.append(IMPLEMENTATION + ":" + impl); + buffer.append("\t"); + } + + String clazz = tagEntry.getClassName(); + if (clazz != null) { + buffer.append(CLASS + ":" + clazz); + buffer.append("\t"); + } + return buffer.toString().trim(); + } + + public void print() { + System.out.println("TagName " + getTagName()); + System.out.println("FileName " + getFileName()); + System.out.println("Pattern " + getPattern()); + System.out.println("LineNumber " + getLineNumber()); + System.out.println("Kind " + getKind()); + System.out.println("Language " + getLanguage()); + System.out.println("FileScope " + hasFileScope()); + String[] inherits = getInherits(); + for (int i = 0; i < inherits.length; i++) { + System.out.println("Inherit " + inherits[i]); + } + System.out.println("AccessControl " + getAccessControl()); + System.out.println("Implementation " + getImplementation()); + System.out.println("ClassName " + getClassName()); + } +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsFileReader.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsFileReader.java new file mode 100644 index 00000000000..07983996d1c --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsFileReader.java @@ -0,0 +1,62 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.cdt.core.index.ITagEntry; + +public class CTagsFileReader { + String filename = null; + List list = null; + + public CTagsFileReader(String name) { + filename = name; + } + + private void parse(BufferedReader reader) throws IOException { + CTagsHeader header = new CTagsHeader(); + // Skip the header. + header.parse(reader); + String s; + while ((s = reader.readLine()) != null) { + ITagEntry entry = new CTagsEntry(s, null); + list.add(entry); + // System.out.println (entry.getLine() + "\n\n"); + // entry.print(); System.out.println(); + } + } + + public ITagEntry[] getTagEntries() throws IOException { + if (list == null) { + list = new LinkedList(); + BufferedReader reader = new BufferedReader(new FileReader(filename)); + parse(reader); + } + return (ITagEntry[])list.toArray(new ITagEntry[0]); + } + + public static void main(String[] args) { + try { + CTagsFileReader tagfile = new CTagsFileReader(args[0]); + ITagEntry[] entries = tagfile.getTagEntries(); + for (int i = 0; i < entries.length; i++) { + if (entries[i] instanceof CTagsEntry) { + CTagsEntry entry = (CTagsEntry)entries[i]; + System.out.println(entry.getLine() + "\n\n"); + entry.print(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsFileWriter.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsFileWriter.java new file mode 100644 index 00000000000..6914f22aae2 --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsFileWriter.java @@ -0,0 +1,61 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; + +import org.eclipse.cdt.core.index.ITagEntry; + +public class CTagsFileWriter { + BufferedWriter writer = null; + ITagEntry [] entries = null; + + public CTagsFileWriter(String tagfile) throws IOException { + writer = new BufferedWriter(new FileWriter(tagfile)); + } + + public CTagsFileWriter(Writer outfile) { + writer = new BufferedWriter(outfile); + } + + public void save(ITagEntry[] ent) throws IOException { + setTagEntries(ent); + save(); + } + + public void save() throws IOException { + if (entries != null) { + String header = CTagsHeader.header(); + writer.write(header, 0, header.length()); + for (int i = 0; i < entries.length; i++) { + String entry = entries[i].getLine(); + writer.write(entry, 0, entry.length()); + writer.newLine(); + } + writer.flush(); + entries = null; + } + } + + public void setTagEntries(ITagEntry[] ent) { + entries = ent; + } + + public static void main(String[] args) { + try { + CTagsFileReader inFile = new CTagsFileReader(args[0]); + ITagEntry[] entries = inFile.getTagEntries(); + CTagsFileWriter outFile = new CTagsFileWriter(args[0] + ".back"); + outFile.save(entries); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsHeader.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsHeader.java new file mode 100644 index 00000000000..1398f8bf6df --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsHeader.java @@ -0,0 +1,96 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.io.IOException; +import java.io.BufferedReader; + + +/* This structure contains information about the tag file. */ +public class CTagsHeader { + + final static String TAG_FILE_FORMAT = + "!_TAG_FILE_FORMAT\t2\t/extended format; --format=1 will not append ;\" to lines/"; + final static String TAG_FILE_SORTED = + "!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/"; + final static String TAG_PROGRAM_AUTHOR = + "!_TAG_PROGRAM_AUTHOR\tDarren Hiebert\t/dhiebert@users.sourceforge.net/"; + final static String TAG_PROGRAM_NAME = + "!_TAG_PROGRAM_NAME\tExuberant Ctags\t//"; + final static String TAG_PROGRAM_URL = + "!_TAG_PROGRAM_URL\thttp://ctags.sourceforge.net\t/official site/"; + final static String TAG_PROGRAM_VERSION = + "!_TAG_PROGRAM_VERSION\t5.2.3\t//"; + + /* information about the structure of the tag file */ + + final String TAGS_PREFIX = "!_"; + + /* Format of tag file (1 = original, 2 = extended) */ + String format; + + /* Is the tag file sorted? (0 = unsorted, 1 = sorted) */ + String sorted; + + /* Information about the program which created this tag file */ + + /* Name of author of generating program (may be null) */ + String author; + + /* Name of program (may be null) */ + String name; + + /* URL of distribution (may be null) */ + String url; + + /* program version (may be null) */ + String version; + + void parse (BufferedReader in) throws IOException { + // !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ + format = in.readLine(); + if (format == null || !format.equals(TAG_FILE_FORMAT)) { + throw new IOException("Wrong Tag Format Header"); + } + + // !_TAG_FILE_SORTED 0 /0=unsorted, 1=sorted/ + sorted = in.readLine(); + if (sorted == null || !sorted.equals(TAG_FILE_SORTED)) { + throw new IOException("Wrong Tag Format Header"); + } + + // !_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ + author = in.readLine(); + if (author == null || !author.equals(TAG_PROGRAM_AUTHOR)) { + throw new IOException("Wrong Tag Format Header"); + } + + // !_TAG_PROGRAM_NAME Exuberant Ctags // + name = in.readLine(); + if (name == null || !name.equals(TAG_PROGRAM_NAME)) { + throw new IOException("Wrong Tag Format Header"); + } + + // !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ + url = in.readLine(); + if (url == null || !url.equals(TAG_PROGRAM_URL)) { + throw new IOException("Wrong Tag Format Header"); + } + + // !_TAG_PROGRAM_VERSION 5.2.3 // + version = in.readLine(); + if (version == null || !version.equals(TAG_PROGRAM_VERSION)) { + throw new IOException("Wrong Tag Format Header"); + } + } + + public static String header() { + return + TAG_FILE_FORMAT + "\n" + TAG_FILE_SORTED + "\n" + + TAG_PROGRAM_AUTHOR + "\n" + TAG_PROGRAM_NAME + "\n" + + TAG_PROGRAM_URL + "\n" + TAG_PROGRAM_VERSION + "\n"; + } +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsRunner.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsRunner.java new file mode 100644 index 00000000000..ffb389ec211 --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/CTagsRunner.java @@ -0,0 +1,74 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +import org.eclipse.cdt.core.index.ITagEntry; + +public class CTagsRunner extends Thread { + + IndexManager manager; + + public CTagsRunner(IndexManager indexManager) { + manager = indexManager; + setDaemon(true); + } + + public void run () { + // It should be ok since we are being started on startup + // the delay should allow things to settle down. + manager.delay(); + while (true) { + IResource resource = null; + RequestList requestList = manager.getRequestList(); + try { + resource = requestList.removeItem(); + } catch (Exception e) { + //e.printStackTrace(); + } + + if (resource != null) { + switch (resource.getType()) { + case IResource.FILE: + IProject project = resource.getProject(); + Map projectsMap = manager.getProjectsMap(); + Map filesMap = (Map)projectsMap.get(project.getLocation()); + if (filesMap == null) { + Map m = Collections.synchronizedMap(new HashMap()); + projectsMap.put(project.getLocation(), m); + // Kick Start; + manager.addContainer(project); + } else { + try { + CTagsCmd cmd = new CTagsCmd(); + IFile file = (IFile)resource; + String location = file.getLocation().toOSString(); + ITagEntry[] entries = cmd.getTagEntries(file, location); + filesMap.put(resource.getLocation(), entries); + } catch (IOException e) { + } + //System.out.println("indexing " + resource.getName()); + } + break; + + case IResource.FOLDER: + case IResource.PROJECT: + System.out.println("Can not index folders " + resource.getName()); + break; + } + } + //System.out.println("Indexing " + filename); + } + } +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/IndexManager.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/IndexManager.java new file mode 100644 index 00000000000..efa93a00020 --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/IndexManager.java @@ -0,0 +1,291 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.index.ITagEntry; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ElementChangedEvent; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.IElementChangedListener; + +public class IndexManager implements IElementChangedListener { + + RequestList requestList = null; + Thread thread = null; + Map projectsMap = null; + + private static IndexManager indexManager = null; + + private IndexManager() { + } + + public ITagEntry[] query(IProject project, String pattern, boolean ignoreCase, boolean exactMatch) { + Map filesMap = (Map)projectsMap.get(project.getLocation()); + // try to kick start. + if (filesMap == null) { + addContainer(project); + } + List result = new ArrayList(); + filesMap = (Map)projectsMap.get(project.getLocation()); + if (filesMap != null) { + if (pattern == null) + pattern = "*"; //FIXME: is this right null matching all? + // Compile the pattern + StringMatcher matcher = new StringMatcher(pattern, ignoreCase, exactMatch); + Iterator values = filesMap.values().iterator(); + while (values.hasNext()) { + ITagEntry[] entries = (ITagEntry[])values.next(); + for (int j = 0; j < entries.length; j++) { + String tagName = entries[j].getTagName(); + if (tagName != null && matcher.match(tagName)) { + result.add(entries[j]); + } + //if (tagName != null && (pattern == null || tagName.equals(pattern))) { + // result.add(entries[j]); + //} + } + } + } + return (ITagEntry[])result.toArray(new ITagEntry[0]); + } + + protected RequestList getRequestList() { + return requestList; + } + + protected Map getProjectsMap() { + return projectsMap; + } + + protected void init () { + requestList = new RequestList(); + projectsMap = Collections.synchronizedMap(new HashMap()); + CTagsRunner ctags = new CTagsRunner(this); + thread = new Thread(ctags, "C Tags indexer"); + thread.setPriority (Thread.NORM_PRIORITY - 1); + thread.start(); + addAll(); + } + + /** + * Before processing all jobs, need to ensure that the indexes are up to date. + */ + protected static void delay() { + try { + // wait 10 seconds so as not to interfere with plugin startup + Thread.currentThread().sleep(10000); + } catch (InterruptedException ie) { + } + } + + /** + * About to delete a project. + */ + public void removeResource(IResource resource) { + Map filesMap = (Map)projectsMap.get(resource.getProject().getLocation()); + if (filesMap == null) + return; + + switch (resource.getType()) { + case IResource.ROOT: + // PROBLEM? + break; + + case IResource.PROJECT: + projectsMap.remove(resource.getLocation()); + break; + + case IResource.FOLDER: + removeFolder((IFolder)resource); + break; + + case IResource.FILE: + removeFile((IFile)resource); + break; + } + } + + public void removeFolder(IFolder folder) { + Map filesMap = (Map)projectsMap.get(folder.getProject().getLocation()); + if (filesMap == null) + return; + + IPath folderPath = folder.getLocation(); + if (filesMap != null) { + Iterator keys = filesMap.keySet().iterator(); + while (keys.hasNext()) { + IPath p = (IPath)keys.next(); + if (p != null && folderPath.isPrefixOf(p)) { +//System.out.println("Removing [" + folderPath + "] " + p); + filesMap.remove(p); + } + } + } + } + + public void removeFile(IFile file) { + Map filesMap = (Map)projectsMap.get(file.getProject().getLocation()); + if (filesMap != null) { + filesMap.remove(file.getLocation()); + } + } + + public void addResource(IResource resource) { + switch(resource.getType()) { + case IResource.ROOT: + case IResource.PROJECT: + case IResource.FOLDER: + addContainer((IContainer)resource); + break; + + case IResource.FILE: + addFile((IFile)resource); + break; + } + } + + /** + * Trigger addition of a resource to an index + * Note: the actual operation is performed in background + */ + public void addFile(IFile file) { + if (CoreModel.getDefault().isTranslationUnit(file)) { + requestList.addItem(file); + } + } + + /** + * Trigger addition of the entire content of a project + * Note: the actual operation is performed in background + */ + public void addContainer(IContainer container) { + if (container != null && container.exists()) { + try { + IResource[] resources = container.members(false); + for (int i = 0; i < resources.length; i++) { + IResource res = resources[i]; + switch(res.getType()) { + case IResource.ROOT: + break; + + case IResource.PROJECT: + if (CoreModel.getDefault().hasCNature((IProject)res)) { + addContainer((IContainer)res); + } + break; + + case IResource.FOLDER: + addContainer((IContainer)res); + break; + + case IResource.FILE: + addFile((IFile)res); + break; + } + } + } catch (CoreException e) { + e.printStackTrace(); + } + } + } + + public void addAll() { + addResource(ResourcesPlugin.getWorkspace().getRoot()); + } + + public void saveIndexes() { + } + + public void saveIndex(IProject project) { + } + + public void shutdown() { + if (thread != null) + thread.interrupted(); + CoreModel.getDefault().removeElementChangedListener(this); + } + + public static IndexManager getDefault() { + if (indexManager == null) { + indexManager = new IndexManager(); + indexManager.init(); + // Register to the C Core Model for C specific changes. + CoreModel.getDefault().addElementChangedListener(indexManager); + } + return indexManager; + } + + protected void processDelta(ICElementDelta delta) throws CModelException { + int kind= delta.getKind(); + int flags= delta.getFlags(); + ICElement element= delta.getElement(); + + //System.out.println("Index Processing Delta " + element); + // handle open and closing of a solution or project + if (((flags & ICElementDelta.F_CLOSED) != 0) + || ((flags & ICElementDelta.F_OPENED) != 0)) { + } + + if (kind == ICElementDelta.REMOVED) { + try { + IResource resource = ((ICElement)element).getCorrespondingResource(); + removeResource(resource); + } catch (CModelException e) { + } + } + + if (kind == ICElementDelta.ADDED) { + try { + IResource resource = ((ICElement)element).getCorrespondingResource(); + addResource(resource); + } catch (CModelException e) { + } + } + + if (element instanceof ITranslationUnit) { + if (kind == ICElementDelta.CHANGED) { + IResource resource = ((ICElement)element).getCorrespondingResource(); + addResource(resource); + return; + } + } + + ICElementDelta[] affectedChildren= delta.getAffectedChildren(); + for (int i= 0; i < affectedChildren.length; i++) { + processDelta(affectedChildren[i]); + } + } + + /* (non-Cdoc) + * Method declared on IElementChangedListener. + */ + public void elementChanged(final ElementChangedEvent event) { + try { + processDelta(event.getDelta()); + } catch(CModelException e) { + e.printStackTrace(); + } + } +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/RequestList.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/RequestList.java new file mode 100644 index 00000000000..140e1113205 --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/RequestList.java @@ -0,0 +1,57 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.*; + +import org.eclipse.core.resources.*; + +public class RequestList { + + private List list; + + public RequestList() { + list = Collections.synchronizedList(new LinkedList()); + } + + public IResource removeItem() throws InterruptedException { + //print("in removeItem() - entering"); + synchronized (list) { + while (list.isEmpty()) { + //print("in removeItem() - about to wait()"); + list.wait(); + //print("in removeItem() - done with wait()"); + } + + // extract the new first item + IResource item = (IResource)list.remove(0); + + //print("in removeItem() - leaving"); + return item; + } + } + + public void addItem(IResource item) { + //print("in addItem() - entering"); + synchronized (list) { + // There will always be room to add to this List + // because it expands as needed. + list.add(item); + //print("in addItem - just added: '" + item + "'"); + + // After adding, notify any and all waiting + // threads that the list has changed. + list.notifyAll(); + //print("in addItem() - just notified"); + } + //print("in addItem() - leaving"); + } + + private static void print(String msg) { + String name = Thread.currentThread().getName(); + System.out.println(name + ": " + msg); + } +} diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/StringMatcher.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/StringMatcher.java new file mode 100644 index 00000000000..48135ae87ad --- /dev/null +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/StringMatcher.java @@ -0,0 +1,389 @@ +package org.eclipse.cdt.internal.core.index; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +import java.util.Vector; + +public class StringMatcher { + protected String fPattern; + protected int fLength; // pattern length + protected boolean fIgnoreWildCards; + protected boolean fIgnoreCase; + protected boolean fHasLeadingStar; + protected boolean fHasTrailingStar; + protected String fSegments[]; //the given pattern is split into * separated segments + + /* boundary value beyond which we don't need to search in the text */ + protected int fBound= 0; + + protected static final char fSingleWildCard= '\u0000'; + + public static class Position { + int start; //inclusive + int end; //exclusive + public Position(int start, int end) { + this.start= start; + this.end= end; + } + public int getStart() { + return start; + } + public int getEnd() { + return end; + } + } + + /** + * Find the first occurrence of the pattern between startend(exclusive). + * @param text, the String object to search in + * @param start, the starting index of the search range, inclusive + * @param end, the ending index of the search range, exclusive + * @return an StringMatcher.Position object that keeps the starting + * (inclusive) and ending positions (exclusive) of the first occurrence of the + * pattern in the specified range of the text; return null if not found or subtext + * is empty (start==end). A pair of zeros is returned if pattern is empty string + * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc" + * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned + */ + + public StringMatcher.Position find(String text, int start, int end) { + if (fPattern == null || text == null) + throw new IllegalArgumentException(); + + int tlen= text.length(); + if (start < 0) + start= 0; + if (end > tlen) + end= tlen; + if (end < 0 || start >= end) + return null; + if (fLength == 0) + return new Position(start, start); + if (fIgnoreWildCards) { + int x= posIn(text, start, end); + if (x < 0) + return null; + return new Position(x, x + fLength); + } + + int segCount= fSegments.length; + if (segCount == 0) //pattern contains only '*'(s) + return new Position(start, end); + + int curPos= start; + int matchStart= -1; + for (int i= 0; i < segCount && curPos < end; ++i) { + String current= fSegments[i]; + int nextMatch= regExpPosIn(text, curPos, end, current); + if (nextMatch < 0) + return null; + if (i == 0) + matchStart= nextMatch; + curPos= nextMatch + current.length(); + } + return new Position(matchStart, curPos); + } + /** + * StringMatcher constructor takes in a String object that is a simple + * pattern which may contain *  for 0 and many characters and + * ?  for exactly one character. Also takes as parameter a boolean object + * specifying if case should be ignored + * @deprecated Use StringMatcher(pattern, ignoreCase, ignoreWildCards). + */ + public StringMatcher(String aPattern, boolean ignoreCase) { + this(aPattern, ignoreCase, false); + } + /** + * StringMatcher constructor takes in a String object that is a simple + * pattern which may contain *  for 0 and many characters and + * ?  for exactly one character. + * + * Literal '*' and '?' characters must be escaped in the pattern + * e.g., "\*" means literal "*", etc. + * + * Escaping any other character (including the escape character itself), + * just results in that character in the pattern. + * e.g., "\a" means "a" and "\\" means "\" + * + * If invoking the StringMatcher with string literals in Java, don't forget + * escape characters are represented by "\\". + * + * @param aPattern the pattern to match text against + * @param ignoreCase if true, case is ignored + * @param ignoreWildCards if true, wild cards and their escape sequences are ignored + * (everything is taken literally). + */ + public StringMatcher(String aPattern, boolean ignoreCase, boolean ignoreWildCards) { + fIgnoreCase= ignoreCase; + fIgnoreWildCards= ignoreWildCards; + fLength= aPattern.length(); + + /* convert case */ + if (fIgnoreCase) { + fPattern= aPattern.toUpperCase(); + } else { + fPattern= aPattern; + } + + if (fIgnoreWildCards) { + parseNoWildCards(); + } else { + parseWildCards(); + } + } + /** + * Given the starting (inclusive) and the ending (exclusive) poisitions in the + * text, determine if the given substring matches with aPattern + * @return true if the specified portion of the text matches the pattern + * @param String text, a String object that contains the substring to match + * @param int start marks the starting position (inclusive) of the substring + * @param int end marks the ending index (exclusive) of the substring + */ + public boolean match(String text, int start, int end) { + if (null == fPattern || null == text) + throw new IllegalArgumentException(); + + if (start > end) + return false; + + if (fIgnoreWildCards) + return fPattern.regionMatches(fIgnoreCase, 0, text, start, fLength); + int segCount= fSegments.length; + if (segCount == 0) //pattern contains only '*'(s) or empty pattern + return true; + if (start == end) + return fLength == 0; + if (fLength == 0) + return start == end; + + int tlen= text.length(); + if (start < 0) + start= 0; + if (end > tlen) + end= tlen; + + int tCurPos= start; + int bound= end - fBound; + if (bound < 0) + return false; + int i= 0; + String current= fSegments[i]; + int segLength= current.length(); + + /* process first segment */ + if (!fHasLeadingStar) { + if (!regExpRegionMatches(text, start, current, 0, segLength)) { + return false; + } else { + ++i; + tCurPos= tCurPos + segLength; + } + } + + /* process middle segments */ + for (; i < segCount && tCurPos <= bound; ++i) { + current= fSegments[i]; + int currentMatch; + int k= current.indexOf(fSingleWildCard); + if (k < 0) { + currentMatch= textPosIn(text, tCurPos, end, current); + if (currentMatch < 0) + return false; + } else { + currentMatch= regExpPosIn(text, tCurPos, end, current); + if (currentMatch < 0) + return false; + } + tCurPos= currentMatch + current.length(); + } + + /* process final segment */ + if (!fHasTrailingStar && tCurPos != end) { + int clen= current.length(); + return regExpRegionMatches(text, end - clen, current, 0, clen); + } + return i == segCount; + } + /** + * match the given text with the pattern + * @return true if matched eitherwise false + * @param text, a String object + */ + public boolean match(String text) { + return match(text, 0, text.length()); + } + /** + * This method parses the given pattern into segments seperated by wildcard '*' characters. + * Since wildcards are not being used in this case, the pattern consists of a single segment. + */ + private void parseNoWildCards() { + fSegments= new String[1]; + fSegments[0]= fPattern; + fBound= fLength; + } + /** + * This method parses the given pattern into segments seperated by wildcard '*' characters. + * @param p, a String object that is a simple regular expression with *  and/or ?  + */ + private void parseWildCards() { + if (fPattern.startsWith("*")) //$NON-NLS-1$ + fHasLeadingStar= true; + if (fPattern.endsWith("*")) { //$NON-NLS-1$ + /* make sure it's not an escaped wildcard */ + if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') { + fHasTrailingStar= true; + } + } + + Vector temp= new Vector(); + + int pos= 0; + StringBuffer buf= new StringBuffer(); + while (pos < fLength) { + char c= fPattern.charAt(pos++); + switch (c) { + case '\\' : + if (pos >= fLength) { + buf.append(c); + } else { + char next= fPattern.charAt(pos++); + /* if it's an escape sequence */ + if (next == '*' || next == '?' || next == '\\') { + buf.append(next); + } else { + /* not an escape sequence, just insert literally */ + buf.append(c); + buf.append(next); + } + } + break; + case '*' : + if (buf.length() > 0) { + /* new segment */ + temp.addElement(buf.toString()); + fBound += buf.length(); + buf.setLength(0); + } + break; + case '?' : + /* append special character representing single match wildcard */ + buf.append(fSingleWildCard); + break; + default : + buf.append(c); + } + } + + /* add last buffer to segment list */ + if (buf.length() > 0) { + temp.addElement(buf.toString()); + fBound += buf.length(); + } + + fSegments= new String[temp.size()]; + temp.copyInto(fSegments); + } + /** + * @param text, a string which contains no wildcard + * @param start, the starting index in the text for search, inclusive + * @param end, the stopping point of search, exclusive + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int posIn(String text, int start, int end) { //no wild card in pattern + int max= end - fLength; + + if (!fIgnoreCase) { + int i= text.indexOf(fPattern, start); + if (i == -1 || i > max) + return -1; + return i; + } + + for (int i= start; i <= max; ++i) { + if (text.regionMatches(true, i, fPattern, 0, fLength)) + return i; + } + + return -1; + } + /** + * @param text, a simple regular expression that may only contain '?'(s) + * @param start, the starting index in the text for search, inclusive + * @param end, the stopping point of search, exclusive + * @param p, a simple regular expression that may contains '?' + * @param caseIgnored, wether the pattern is not casesensitive + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int regExpPosIn(String text, int start, int end, String p) { + int plen= p.length(); + + int max= end - plen; + for (int i= start; i <= max; ++i) { + if (regExpRegionMatches(text, i, p, 0, plen)) + return i; + } + return -1; + } + /** + * + * @return boolean + * @param text, a String to match + * @param start, int that indicates the starting index of match, inclusive + * @param end int that indicates the ending index of match, exclusive + * @param p, String, String, a simple regular expression that may contain '?' + * @param ignoreCase, boolean indicating wether code>p is case sensitive + */ + protected boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen) { + while (plen-- > 0) { + char tchar= text.charAt(tStart++); + char pchar= p.charAt(pStart++); + + /* process wild cards */ + if (!fIgnoreWildCards) { + /* skip single wild cards */ + if (pchar == fSingleWildCard) { + continue; + } + } + if (pchar == tchar) + continue; + if (fIgnoreCase) { + char tc= Character.toUpperCase(tchar); + if (tc == pchar) + continue; + } + return false; + } + return true; + } + /** + * @param text, the string to match + * @param start, the starting index in the text for search, inclusive + * @param end, the stopping point of search, exclusive + * @param code>p, a string that has no wildcard + * @param ignoreCase, boolean indicating wether code>p is case sensitive + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int textPosIn(String text, int start, int end, String p) { + + int plen= p.length(); + int max= end - plen; + + if (!fIgnoreCase) { + int i= text.indexOf(p, start); + if (i == -1 || i > max) + return -1; + return i; + } + + for (int i= 0; i <= max; ++i) { + if (text.regionMatches(true, i, p, 0, plen)) + return i; + } + + return -1; + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CModelException.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CModelException.java new file mode 100644 index 00000000000..dbe943a1445 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CModelException.java @@ -0,0 +1,117 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.internal.core.model.CModelStatus; + +/** + * A checked exception representing a failure in the C model. + * C model exceptions contain a C-specific status object describing the + * cause of the exception. + * + * @see ICModelStatus + * @see ICModelStatusConstants + */ +public class CModelException extends CoreException { + /** + * Creates a C model exception that wrappers the given Throwable. + * The exception contains a C-specific status object with severity + * IStatus.ERROR and the given status code. + * + * @param exception the Throwable + * @param code one of the C-specific status codes declared in + * ICModelStatusConstants + * @return the new C model exception + * @see ICModelStatusConstants + * @see org.eclipse.core.runtime.IStatus#ERROR + */ + public CModelException(Throwable e, int code) { + this(new CModelStatus(code, e)); + } + + /** + * Creates a C model exception for the given CoreException. + * Equivalent to + * CModelException(exception,ICModelStatusConstants.CORE_EXCEPTION. + * + * @param exception the CoreException + * @return the new C model exception + */ + public CModelException(CoreException exception) { + this(new CModelStatus(exception)); + } + + /** + * Creates a C model exception for the given C-specific status object. + * + * @param status the C-specific status object + * @return the new C model exception + */ + public CModelException(ICModelStatus status) { + super(status); + } + + /** + * Returns the underlying Throwable that caused the failure. + * + * @return the wrappered Throwable, or null if the + * direct case of the failure was at the C model layer + */ + public Throwable getException() { + return getStatus().getException(); + } + + /** + * Returns the C model status object for this exception. + * Equivalent to (ICModelStatus) getStatus(). + * + * @return a status object + */ + public ICModelStatus getCModelStatus() { + return (ICModelStatus) getStatus(); + } + + /** + * Returns whether this exception indicates that a C model element does not + * exist. Such exceptions have a status with a code of + * ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST. + * This is a convenience method. + * + * @return true if this exception indicates that a C model + * element does not exist + * @see ICModelStatus#doesNotExist + * @see ICModelStatusConstants#ELEMENT_DOES_NOT_EXIST + */ + public boolean doesNotExist() { + ICModelStatus cModelStatus = getCModelStatus(); + return cModelStatus != null && cModelStatus.doesNotExist(); + } + + /** + * Returns a printable representation of this exception suitable for debugging + * purposes only. + */ + public String toString() { + StringBuffer buffer= new StringBuffer(); + buffer.append("C Model Exception: "); //$NON-NLS-1$ + if (getException() != null) { + if (getException() instanceof CoreException) { + CoreException c= (CoreException)getException(); + buffer.append("Core Exception [code "); //$NON-NLS-1$ + buffer.append(c.getStatus().getCode()); + buffer.append("] "); //$NON-NLS-1$ + buffer.append(c.getStatus().getMessage()); + } else { + buffer.append(getException().toString()); + } + } else { + buffer.append(getStatus().toString()); + } + return buffer.toString(); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java new file mode 100644 index 00000000000..76a09f62266 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModel.java @@ -0,0 +1,252 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; + +//import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.core.model.CModelManager; + +// This should be done in the Plugin. + +public class CoreModel { + + private static CoreModel cmodel = null; + private static CModelManager manager = null; + + /** + * Plugin string id. + */ + public final static String PLUGIN_ID = "org.eclipse.cdt.core"; + + /** + * C nature string name, "cnature". + */ + public final static String C_NATURE_NAME = "cnature"; + /** + * C nature string id, PLUGIN_ID + C_NATURE_NAME + */ + public final static String C_NATURE_ID = PLUGIN_ID + "." + C_NATURE_NAME; + + /** + * C++ nature string name, "ccnature" + */ + public final static String CC_NATURE_NAME = "ccnature"; + /** + * C++ nature string id, PLUGIN_ID + CC_NATURE_NAME + */ + public final static String CC_NATURE_ID = PLUGIN_ID + "." + CC_NATURE_NAME; + + /** + * Returns the plugin id. + */ + public static String getPluginId() { + return PLUGIN_ID; + } + + /** + * Returns the C nature Name. + */ + public static String getCNatureName () { + return C_NATURE_NAME; + } + + /** + * Returns the C++ nature name. + */ + public static String getCCNatureName () { + return CC_NATURE_NAME; + } + + /** + * Returns the C nature Id. + */ + public static String getCNatureId () { + return C_NATURE_ID; + } + + /** + * Returns the C++ nature Id. + */ + public static String getCCNatureId () { + return CC_NATURE_ID; + } + + /** + * Creates an ICElement form and IPath. + * Returns null if not found. + */ + public ICElement create(IPath path) { + return manager.create(path); + } + + /** + * Creates an ICElement form and IFile. + * Returns null if not found. + */ + public ICElement create(IFile file) { + return manager.create(file); + } + + /** + * Creates an ICElement form and IFolder. + * Returns null if not found. + */ + public ICElement create(IFolder folder) { + return manager.create(folder); + } + + /** + * Creates an ICElement form and IProject. + * Returns null if not found. + */ + public ICElement create(IProject project) { + return manager.create(project); + } + + /** + * Creates an ICElement form and IWorkspaceRoot. + * Returns null if not found. + */ + public ICElement create(IWorkspaceRoot root) { + return manager.create(root); + } + + /** + * Creates an ICElement form and IResource. + * Returns null if not found. + */ + public ICElement create(IResource resource) { + return manager.create(resource); + } + + /** + * Returns the default ICRoot. + */ + public ICElement getCRoot() { + return manager.getCRoot(); + } + + /** + * Return true if IFile is a shared library, i.e. libxx.so + */ + public static boolean isSharedLib(IFile file) { + return manager.isSharedLib(file); + } + + /** + * Return true if IFile is a an object(ELF), i.e. *.o + */ + public static boolean isObject(IFile file) { + return manager.isObject(file); + } + + /** + * Return true if IFile is an ELF executable + */ + public static boolean isExecutable(IFile file) { + return manager.isExecutable(file); + } + + /** + * Return true if IFile is an ELF. + */ + public static boolean isBinary(IFile file) { + return manager.isBinary(file); + } + + /** + * Return true if IFile is an Achive, *.a + */ + public static boolean isArchive(IFile file) { + return manager.isArchive(file); + } + + /** + * Return true if IFile is a TranslationUnit. + */ + public static boolean isTranslationUnit(IFile file) { + return manager.isTranslationUnit(file); + } + + /** + * Return true if name is a valid name for a translation unit. + */ + public static boolean isValidTranslationUnitName(String name){ + return manager.isValidTranslationUnitName(name); + } + + /** + * Return true if project has C nature. + */ + public static boolean hasCNature(IProject project){ + return manager.hasCNature(project); + } + + public static boolean hasCCNature(IProject project){ + return manager.hasCCNature(project); + } + + public static void addCNature(IProject project, IProgressMonitor monitor) throws CModelException { + manager.addCNature(project, monitor); + } + + public static void addCCNature(IProject project, IProgressMonitor monitor) throws CModelException { + manager.addCCNature(project, monitor); + } + + public static void removeCNature(IProject project, IProgressMonitor monitor) throws CModelException { + manager.removeCNature(project, monitor); + } + + public static void removeCCNature(IProject project, IProgressMonitor monitor) throws CModelException { + manager.removeCCNature(project, monitor); + } + + public static void addNature(IProject project, String natureId, IProgressMonitor monitor) + throws CModelException { + manager.addNature(project, natureId, monitor); + } + + public static void removeNature(IProject project, String natureId, IProgressMonitor monitor) + throws CModelException { + manager.removeNature(project, natureId, monitor); + } + + /** + * Return the singleton. + */ + public static CoreModel getDefault() { + if (cmodel == null) { + cmodel = new CoreModel(); + manager = CModelManager.getDefault(); + } + return cmodel; + } + + public static void addElementChangedListener(IElementChangedListener listener) { + manager.addElementChangedListener(listener); + } + + /** + * Removes the given element changed listener. + * Has no affect if an identical listener is not registered. + * + * @param listener the listener + */ + public static void removeElementChangedListener(IElementChangedListener listener) { + manager.removeElementChangedListener(listener); + } + + private CoreModel() { + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ElementChangedEvent.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ElementChangedEvent.java new file mode 100644 index 00000000000..92feb5953fa --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ElementChangedEvent.java @@ -0,0 +1,33 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +import java.util.EventObject; + +/** + * An element changed event describes a change to the structure or contents + * of a tree of C elements. The changes to the elements are described by + * the associated delta object carried by this event. + * + * @see IElementChangedListener + * @see ICElementDelta + */ +public class ElementChangedEvent extends EventObject { + /** + * Creates an new element changed event (based on a ICElementDelta). + * + * @param delta the C element delta. + */ + public ElementChangedEvent(ICElementDelta delta) { + super(delta); + } + /** + * Returns the delta describing the change. + * + */ + public ICElementDelta getDelta() { + return (ICElementDelta) source; + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/Flags.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/Flags.java new file mode 100644 index 00000000000..30925076c86 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/Flags.java @@ -0,0 +1,188 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.core.model.IConstants; + +/** + * Utility class for decoding modifier flags in C elements. + *

+ * This class provides static methods only; it is not intended to be + * instantiated or subclassed by clients. + *

+ * + */ +public final class Flags { + /** + * Not instantiable. + */ + private Flags() {} + + /** + * Returns whether the given integer includes the abstract modifier. + * + * @param flags the flags + * @return true if the abstract modifier is included + */ + public static boolean isAbstract(int flags) { + return (flags & IConstants.AccAbstract) != 0; + } + + /** + * + * Return whether the give integer include the keyword export modifier. + * @param flags the flags + * @return true if the element is export + */ + public static boolean isExport(int flags) { + return (flags & IConstants.AccExport) != 0; + } + + /** + * Returns whether the given integer includes the inline modifier. + * + * @param flags the flags + * @return true if the inline modifier is included + */ + public static boolean isInline(int flags) { + return (flags & IConstants.AccInline) != 0; + } + + /** + * Returns whether the given integer includes the explicit modifier. + * + * @param flags the flags + * @return true if explicit modifier is included + */ + public static boolean isExplicit(int flags) { + return (flags & IConstants.AccExplicit) != 0; + } + + /** + * Returns whether the given integer includes the private modifier. + * + * @param flags the flags + * @return true if the private modifier is included + */ + public static boolean isPrivate(int flags) { + return (flags & IConstants.AccPrivate) != 0; + } + + /** + * Returns whether the given integer includes the protected modifier. + * + * @param flags the flags + * @return true if the protected modifier is included + */ + public static boolean isProtected(int flags) { + return (flags & IConstants.AccProtected) != 0; + } + + /** + * Returns whether the given integer includes the public modifier. + * + * @param flags the flags + * @return true if the public modifier is included + */ + public static boolean isPublic(int flags) { + return (flags & IConstants.AccPublic) != 0; + } + + /** + * Returns whether the given integer includes the static modifier. + * + * @param flags the flags + * @return true if the static modifier is included + */ + public static boolean isStatic(int flags) { + return (flags & IConstants.AccStatic) != 0; + } + + /** + * Returns whether the given integer includes the extern modifier. + * + * @param flags the flags + * @return true if the extern modifier is included + */ + public static boolean isExtern(int flags) { + return (flags & IConstants.AccExtern) != 0; + } + /** + * Returns whether the given integer includes the mutable modifier. + * + * @param flags the flags + * @return true if the mutable modifier is included + */ + public static boolean isMutable(int flags) { + return (flags & IConstants.AccMutable) != 0; + } + + /** + * Returns whether the given integer includes the indication that the + * element is a register storage specifier. + * + * @param flags the flags + * @return true if the element is marked register storage specifier + */ + public static boolean isRegister(int flags) { + return (flags & IConstants.AccRegister) != 0; + } + /** + * Returns whether the given integer includes the virtual modifier. + * + * @param flags the flags + * @return true if the virtual modifier is included + */ + public static boolean isVirtual(int flags) { + return (flags & IConstants.AccVirtual) != 0; + } + + /** + * Returns whether the given integer includes the volatile modifier. + * + * @param flags the flags + * @return true if the volatile modifier is included + */ + public static boolean isVolatile(int flags) { + return (flags & IConstants.AccVolatile) != 0; + } + + /** + * Returns a standard string describing the given modifier flags. + * Only modifier flags are included in the output; the deprecated and + * synthetic flags are ignored if set. + *

+ * Examples results: + *

+	 *	  "public static"
+	 *	  "private"
+	 * 
+ *

+ * + * @param flags the flags + * @return the standard string representation of the given flags + */ + public static String toString(int flags) { + StringBuffer sb = new StringBuffer(); + + if (isPublic(flags)) sb.append("public "); //$NON-NLS-1$ + if (isProtected(flags)) sb.append("protected "); //$NON-NLS-1$ + if (isPrivate(flags)) sb.append("private "); //$NON-NLS-1$ + if (isStatic(flags)) sb.append("static "); //$NON-NLS-1$ + if (isAbstract(flags)) sb.append("abstract "); //$NON-NLS-1$ + if (isVirtual(flags)) sb.append("virtual "); //$NON-NLS-1$ + if (isInline(flags)) sb.append("inline "); //$NON-NLS-1$ + if (isExtern(flags)) sb.append("extern "); //$NON-NLS-1$ + if (isExport(flags)) sb.append("export "); //$NON-NLS-1$ + if (isVolatile(flags)) sb.append("volatile "); //$NON-NLS-1$ + if (isExplicit(flags)) sb.append("explicit "); //$NON-NLS-1$ + + int len = sb.length(); + if (len == 0) return ""; //$NON-NLS-1$ + sb.setLength(len-1); + return sb.toString(); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IArchive.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IArchive.java new file mode 100644 index 00000000000..449164dd1b0 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IArchive.java @@ -0,0 +1,18 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * An IArchive represents a group of files combined into a + * single file(the Archive), for example libxx.a. + */ +public interface IArchive extends ICFile { + /** + * Return the binaries contain in the archive. + * It does not actually extract the files. + */ + public IBinary[] getBinaries(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IArchiveContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IArchiveContainer.java new file mode 100644 index 00000000000..8e0f54c9b7a --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IArchiveContainer.java @@ -0,0 +1,14 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represents a container of all the IArchive's found in the project + * while inspecting the project. + */ +public interface IArchiveContainer extends IParent, ICElement { + public IArchive[] getArchives(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IBinary.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IBinary.java new file mode 100644 index 00000000000..1a68f3793b6 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IBinary.java @@ -0,0 +1,35 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represents a Binary file, for example an ELF excutable. + * An ELF parser will inspect the binary. + */ +public interface IBinary extends ICFile { + /** + * Return whether the file was compiling with debug symbols. + */ + public boolean hasDebug(); + + public boolean isExecutable(); + + public boolean isObject(); + + public boolean isSharedLib(); + + public String [] getNeededSharedLibs(); + + public String getSoname(); + + public String getCPU(); + + public long getText(); + + public long getData(); + + public long getBSS(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IBinaryContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IBinaryContainer.java new file mode 100644 index 00000000000..0746357341c --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IBinaryContainer.java @@ -0,0 +1,15 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represents a container of all the IBinary's found in the project + * while inspecting the project. + */ +public interface IBinaryContainer extends IParent, ICElement { + + public IBinary[] getBinaries(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java new file mode 100644 index 00000000000..75660dccca8 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java @@ -0,0 +1,289 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IAdaptable; + +/** + * Common protocol for all elements provided by the C model. + */ +public interface ICElement extends IAdaptable { + + /** + * IResource from 10-20 + */ + + /** + * Constant representing a C Root workspace (IWorkspaceRoot object). + * A C element with this type can be safely cast to ICRoot. + */ + public static final int C_ROOT = 10; + + /** + * Constant representing a C project(IProject object). + * A C element with this type can be safely cast to ICProject. + */ + public static final int C_PROJECT = 11; + + /** + * Constant representing a folder(ICFolder object). + * A C element with this type can be safely cast to ICFolder. + */ + public static final int C_FOLDER = 12; + + /** + * Constant representing a file(ICFile object). + * A C element with this type can be safely cast to ICFile. + */ + public static final int C_FILE = 13; + + /** + * Virtual container serving as a place holder. + */ + public static final int C_CONTAINER = 30; + + /** + * Constant representing a C/C++ children of a Translation Unit + */ + public static final int C_UNIT = 60; + + /** + * Namespace. + */ + public static final int C_NAMESPACE = 61; + + /** + * Using. + */ + public static final int C_USING = 62; + + /** + * Enumeration. + */ + public static final int C_ENUMERATION = 63; + + /** + * Constant representing a class structure. + */ + public static final int C_CLASS = 64; + + /** + * Constant representing a struct structure. + */ + public static final int C_STRUCT = 65; + + /** + * Constant representing a union structure. + */ + public static final int C_UNION = 66; + + /** + * A method definition part of a structure(class, struct, union). + */ + public static final int C_METHOD = 67; + + /** + * A method declaration part of a structure(class, struct, union). + */ + public static final int C_METHOD_DECLARATION = 68; + + /** + * A Field definition part of a structure(class, struct, union). + */ + public static final int C_FIELD = 69; + + /** + * a C/C++ function prototype. + */ + public static final int C_FUNCTION_DECLARATION = 70; + + /** + * a C/C++ function. + */ + public static final int C_FUNCTION = 71; + + /** + * Preprocessor #include directive. + */ + public static final int C_INCLUDE = 72; + + /** + * C++ template class. + */ + public static final int C_TEMPLATE = 73; + + /** + * Global variable. + */ + public static final int C_VARIABLE = 74; + + /** + * variable Declaration. + */ + public static final int C_VARIABLE_DECLARATION = 75; + + /** + * Local Variable. + */ + public static final int C_VARIABLE_LOCAL = 76; + + /** + * A preprocessor macro. + */ + public static final int C_MACRO = 77; + + /** + * a Typedef. + */ + public static final int C_TYPEDEF = 78; + + /** + * Modifier indicating a class constructor + */ + public static final int C_CLASS_CTOR = 0x100; + + /** + * Modifier indicating a class destructor + */ + public static final int C_CLASS_DTOR = 0x200; + + /** + * Modifier indicating a static storage attribute + */ + public static final int C_STORAGE_STATIC = 0x400; + + /** + * Modifier indicating an extern storage attribute + */ + public static final int C_STORAGE_EXTERN = 0x800; + + /** + * Modifier indicating a private class + */ + public static final int CPP_PRIVATE = 0x1000; + + /** + * Modifier indicating a public class + */ + + public static final int CPP_PUBLIC = 0x2000; + + /** + * Modifier indicating a friend class + */ + public static final int CPP_FRIEND = 0x4000; + + /** + * Returns whether this C element exists in the model. + * + * @return true if this element exists in the C model + */ + boolean exists(); + + /** + * Returns the resource that corresponds directly to this element, + * or null if there is no resource that corresponds to + * this element. + *

+ * For example, the corresponding resource for an ATranslationUnit + * is its underlying IFile. + * + * @return the corresponding resource, or null if none + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + IResource getCorrespondingResource() throws CModelException; + + /** + * Returns the name of this element. + * + * @return the element name + */ + String getElementName(); + + /** + * Returns this element's kind encoded as an integer. + * This is a handle-only method. + * + * @return the kind of element; one of the constants declared in + * ICElement + * @see ICElement + */ + public int getElementType(); + + /** + * Returns the C model. + * + * @return the C model + */ + ICRoot getCRoot(); + + /** + * Returns the C project this element is contained in, + * or null if this element is not contained in any C project + * + * @return the containing C project, or null if this element is + * not contained in a C project + */ + ICProject getCProject(); + + /** + * Returns the element directly containing this element, + * or null if this element has no parent. + * + * @return the parent element, or null if this element has no parent + */ + ICElement getParent(); + + /** + * Returns the path to the innermost resource enclosing this element. + * If this element is not included in an external archive, + * the path returned is the full, absolute path to the underlying resource, + * relative to the workbench. + * If this element is included in an external archive, + * the path returned is the absolute path to the archive in the file system. + * This is a handle-only method. + * + */ + IPath getPath(); + + /** + * Returns the underlying resource that contains + * this element, or null if this element is not contained + * in a resource. + * + * @return the underlying resource, or null if none + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its underlying resource + */ + IResource getUnderlyingResource() throws CModelException; + + /** + * Returns whether this C element is read-only. An element is read-only + * if its structure cannot be modified by the C model. + * + * @return true if this element is read-only + */ + boolean isReadOnly(); + + /** + * Returns whether the structure of this element is known. For example, for a + * translation unit that could not be parsed, false is returned. + * If the structure of an element is unknown, navigations will return reasonable + * defaults. For example, getChildren will return an empty collection. + *

+ * Note: This does not imply anything about consistency with the + * underlying resource/buffer contents. + *

+ * + * @return true if the structure of this element is known + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + boolean isStructureKnown() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElementDelta.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElementDelta.java new file mode 100644 index 00000000000..680d2f5698c --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElementDelta.java @@ -0,0 +1,187 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +import org.eclipse.core.resources.IResourceDelta; + +/** + * A C element delta describes changes in C element between two discrete + * points in time. Given a delta, clients can access the element that has + * changed, and any children that have changed. + *

+ * Deltas have a different status depending on the kind of change they represent. + * The list below summarizes each status (as returned by getKind) + * and its meaning: + *

+ *

+ * Move operations are indicated by other change flags, layered on top + * of the change flags described above. If element A is moved to become B, + * the delta for the change in A will have status REMOVED, + * with change flag F_MOVED_TO. In this case, + * getMovedToElement on delta A will return the handle for B. + * The delta for B will have status ADDED, with change flag + * F_MOVED_FROM, and getMovedFromElement on delta + * B will return the handle for A. (Note, the handle to A in this case represents + * an element that no longer exists). + *

+ *

+ * Note that the move change flags only describe the changes to a single element, they + * do not imply anything about the parent or children of the element. + */ +public interface ICElementDelta { + + /** + * Status constant indicating that the element has been added. + */ + public int ADDED = 1; + + /** + * Status constant indicating that the element has been removed. + */ + public int REMOVED = 2; + + /** + * Status constant indicating that the element has been changed, + * as described by the change flags. + */ + public int CHANGED = 4; + + /** + * Change flag indicating that the content of the element has changed. + */ + public int F_CONTENT = 0x0001; + + /** + * Change flag indicating that the modifiers of the element have changed. + */ + public int F_MODIFIERS = 0x0002; + + /** + * Change flag indicating that there are changes to the children of the element. + */ + public int F_CHILDREN = 0x0008; + + /** + * Change flag indicating that the element was moved from another location. + * The location of the old element can be retrieved using getMovedFromElement. + */ + public int F_MOVED_FROM = 0x0010; + + /** + * Change flag indicating that the element was moved to another location. + * The location of the new element can be retrieved using getMovedToElement. + */ + public int F_MOVED_TO = 0x0020; + + /** + * Change flag indicating that the underlying IProject has been + * opened. + */ + public int F_OPENED = 0x0200; + + /** + * Change flag indicating that the underlying IProject has been + * closed. + */ + public int F_CLOSED = 0x0400; + + //public int F_ADDED_TO_CLASSPATH = 0x0040; + //public int F_REMOVED_FROM_CLASSPATH = 0x0080; + //public int F_CLASSPATH_REORDER = 0x0100; + //public int F_SUPER_TYPES = 0x0800; + + /** + * Change flag indicating that a source jar has been attached to a binary jar. + */ + public int F_SOURCEATTACHED = 0x1000; + + /** + * Change flag indicating that a source jar has been detached to a binary jar. + */ + public int F_SOURCEDETACHED = 0x2000; + + /** + * Change flag indicating that this is a fine-grained delta, i.e. an analysis down + * to the members level was done to determine if there were structural changes to + * members. + */ + public int F_FINE_GRAINED = 0x4000; + + /** + * Returns deltas for the children that have been added. + */ + public ICElementDelta[] getAddedChildren(); + + /** + * Returns deltas for the affected (added, removed, or changed) children. + */ + public ICElementDelta[] getAffectedChildren(); + + /** + * Returns deltas for the children which have changed. + */ + public ICElementDelta[] getChangedChildren(); + + /** + * Returns the element that this delta describes a change to. + */ + public ICElement getElement(); + + /** + * Returns flags that describe how an element has changed. + * + * @see ICElementDelta#F_CHILDREN + * @see ICElementDelta#F_CONTENT + * @see ICElementDelta#F_MODIFIERS + * @see ICElementDelta#F_MOVED_FROM + * @see ICElementDelta#F_MOVED_TO + */ + public int getFlags(); + + /** + * Returns the kind of this delta - one of ADDED, REMOVED, + * or CHANGED. + */ + public int getKind(); + + /** + * Returns an element describing this element before it was moved + * to its current location, or null if the + * F_MOVED_FROM change flag is not set. + */ + public ICElement getMovedFromElement(); + + /** + * Returns an element describing this element in its new location, + * or null if the F_MOVED_TO change + * flag is not set. + */ + public ICElement getMovedToElement(); + + /** + * Returns deltas for the children which have been removed. + */ + public ICElementDelta[] getRemovedChildren(); + + /** + * Returns the collection of resource deltas. + *

+ * Note that resource deltas, like C element deltas, are generally only valid + * for the dynamic scope of an event notification. Clients must not hang on to + * these objects. + *

+ * + * @return the underlying resource deltas, or null if none + */ + public IResourceDelta[] getResourceDeltas(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICFile.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICFile.java new file mode 100644 index 00000000000..ef747add31e --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICFile.java @@ -0,0 +1,22 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IFile; + +/** + * A C File Resource. + */ +public interface ICFile extends IParent, ICElement { + + public boolean isBinary(); + + public boolean isArchive(); + + public boolean isTranslationUnit(); + + public IFile getFile(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICFolder.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICFolder.java new file mode 100644 index 00000000000..42eefe863d7 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICFolder.java @@ -0,0 +1,16 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IFolder; + +/** + * A C Folder Resource. + */ +public interface ICFolder extends IParent, ICElement { + + public IFolder getFolder(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java new file mode 100644 index 00000000000..512e88573c9 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelMarker.java @@ -0,0 +1,35 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.cdt.internal.CCorePlugin; + + +/** + * Markers used by the C model. + *

+ * This interface declares constants only; it is not intended to be implemented + * or extended. + *

+ */ +public interface ICModelMarker { + + /** + * C model problem marker type (value "org.eclipse.cdt.core.problem"). + * This can be used to recognize those markers in the workspace that flag problems + * detected by the C ompilers. + */ + public static final String C_MODEL_PROBLEM_MARKER = CCorePlugin.PLUGIN_ID + ".problem"; //$NON-NLS-1$ + + /** + * C model extension to the marker problem markers which may hold a hint on + * the variable name that caused the error. Used by the ui to highlight the variable + * itself if it can be found. + */ + public static final String C_MODEL_MARKER_VARIABLE = "problem.variable"; //$NON-NLS-1$ +} + + diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelStatus.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelStatus.java new file mode 100644 index 00000000000..f62c6d50faa --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelStatus.java @@ -0,0 +1,79 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; + +/** + * Represents the outcome of an C model operation. Status objects are + * used inside CModelException objects to indicate what went + * wrong. + *

+ * C model status object are distinguished by their plug-in id: + * getPlugin returns "org.eclipse.cdt.core". + * getCode returns one of the status codes declared in + * ICModelStatusConstants. + *

+ *

+ * A C model status may also carry additional information (that is, in + * addition to the information defined in IStatus): + *

+ *

+ * This interface is not intended to be implemented by clients. + *

+ * + * @see org.eclipse.core.runtime.IStatus + * @see ICModelStatusConstants + */ +public interface ICModelStatus extends IStatus { + /** + * Returns any C elements associated with the failure (see specification + * of the status code), or an empty array if no elements are related to this + * particular status code. + * + * @return the list of C element culprits + * @see ICModelStatusConstants + */ + ICElement[] getElements(); + + /** + * Returns the path associated with the failure (see specification + * of the status code), or null if the failure is not + * one of DEVICE_PATH, INVALID_PATH, + * PATH_OUTSIDE_PROJECT, or RELATIVE_PATH. + * + * @return the path that caused the failure, or null if none + * @see ICModelStatusConstants#DEVICE_PATH + * @see ICModelStatusConstants#INVALID_PATH + * @see ICModelStatusConstants#PATH_OUTSIDE_PROJECT + * @see ICModelStatusConstants#RELATIVE_PATH + */ + IPath getPath(); + + /** + * Returns the string associated with the failure (see specification + * of the status code), or null if no string is related to this + * particular status code. + * + * @return the string culprit, or null if none + * @see ICModelStatusConstants + */ + String getString(); + + /** + * Returns whether this status indicates that a C model element does not exist. + * This convenience method is equivalent to + * getCode() == ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST. + * + * @return true if the status code indicates that a C model + * element does not exist + * @see ICModelStatusConstants#ELEMENT_DOES_NOT_EXIST + */ + boolean doesNotExist(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelStatusConstants.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelStatusConstants.java new file mode 100644 index 00000000000..21fe3c6a202 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICModelStatusConstants.java @@ -0,0 +1,224 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Status codes used with C model status objects. + *

+ * This interface declares constants only; it is not intended to be implemented + * or extended. + *

+ * + * @see ICModelStatus + * @see org.eclipse.core.runtime.IStatus#getCode + */ +public interface ICModelStatusConstants { + + /** + * Status constant indicating that a variable path was not resolvable + * indicating either the referred variable is undefined, unbound or the resolved + * variable path does not correspond to an existing file or folder. + */ + public static final int CP_VARIABLE_PATH_UNBOUND = 965; + + /** + * Status constant indicating a core exception occurred. + * Use getException to retrieve a CoreException. + */ + public static final int CORE_EXCEPTION = 966; + + /** + * Status constant indicating one or more of the elements + * supplied are not of a valid type for the operation to + * process. + * The element(s) can be retrieved using getElements on the status object. + */ + public static final int INVALID_ELEMENT_TYPES = 967; + + /** + * Status constant indicating that no elements were + * provided to the operation for processing. + */ + public static final int NO_ELEMENTS_TO_PROCESS = 968; + + /** + * Status constant indicating that one or more elements + * supplied do not exist. + * The element(s) can be retrieved using getElements on the status object. + * + * @see ICModelStatus#isDoesNotExist + */ + public static final int ELEMENT_DOES_NOT_EXIST = 969; + + /** + * Status constant indicating that a null path was + * supplied to the operation. + */ + public static final int NULL_PATH = 970; + + /** + * Status constant indicating that a path outside of the + * project was supplied to the operation. The path can be retrieved using + * getPath on the status object. + */ + public static final int PATH_OUTSIDE_PROJECT = 971; + + /** + * Status constant indicating that a relative path + * was supplied to the operation when an absolute path is + * required. The path can be retrieved using getPath on the + * status object. + */ + public static final int RELATIVE_PATH = 972; + + /** + * Status constant indicating that a path specifying a device + * was supplied to the operation when a path with no device is + * required. The path can be retrieved using getPath on the + * status object. + */ + public static final int DEVICE_PATH = 973; + + /** + * Status constant indicating that a string + * was supplied to the operation that was null. + */ + public static final int NULL_STRING = 974; + + /** + * Status constant indicating that the operation encountered + * a read-only element. + * The element(s) can be retrieved using getElements on the status object. + */ + public static final int READ_ONLY = 976; + + /** + * Status constant indicating that a naming collision would occur + * if the operation proceeded. + */ + public static final int NAME_COLLISION = 977; + + /** + * Status constant indicating that a destination provided for a copy/move/rename operation + * is invalid. + * The destination element can be retrieved using getElements on the status object. + */ + public static final int INVALID_DESTINATION = 978; + + /** + * Status constant indicating that a path provided to an operation + * is invalid. The path can be retrieved using getPath on the + * status object. + */ + public static final int INVALID_PATH = 979; + + /** + * Status constant indicating the given source position is out of bounds. + */ + public static final int INDEX_OUT_OF_BOUNDS = 980; + + /** + * Status constant indicating there is an update conflict + * for a working copy. The translation unit on which the + * working copy is based has changed since the working copy + * was created. + */ + public static final int UPDATE_CONFLICT = 981; + + /** + * Status constant indicating that null was specified + * as a name argument. + */ + public static final int NULL_NAME = 982; + + /** + * Status constant indicating that a name provided is not syntactically correct. + * The name can be retrieved from getString. + */ + public static final int INVALID_NAME = 983; + + /** + * Status constant indicating that the specified contents + * are not valid. + */ + public static final int INVALID_CONTENTS = 984; + + /** + * Status constant indicating that an java.io.IOException + * occurred. + */ + public static final int IO_EXCEPTION = 985; + + /** + * Status constant indicating that a DOMException + * occurred. + */ + public static final int DOM_EXCEPTION = 986; + + /** + * Status constant indicating that a TargetException + * occurred. + */ + public static final int TARGET_EXCEPTION = 987; + + /** + * Status constant indicating that the C builder + * could not be initialized. + */ + public static final int BUILDER_INITIALIZATION_ERROR = 990; + + /** + * Status constant indicating that the C builder's last built state + * could not be serialized or deserialized. + */ + public static final int BUILDER_SERIALIZATION_ERROR = 991; + + /** + * Status constant indicating that an error was encountered while + * trying to evaluate a code snippet, or other item. + */ + public static final int EVALUATION_ERROR = 992; + + /** + * Status constant indicating that a sibling specified is not valid. + */ + public static final int INVALID_SIBLING = 993; + + /** + * Status indicating that a C element could not be created because + * the underlying resource is invalid. + * @see CCore + */ + public static final int INVALID_RESOURCE = 995; + + /** + * Status indicating that a C element could not be created because + * the underlying resource is not of an appropriate type. + * @see CCore + */ + public static final int INVALID_RESOURCE_TYPE = 996; + + /** + * Status indicating that a C element could not be created because + * the project owning underlying resource does not have the C nature. + * @see CCore + */ + public static final int INVALID_PROJECT = 997; + + //public static final int INVALID_NAMESPACE = 998; + + /** + * Status indicating that the corresponding resource has no local contents yet. + * This might happen when attempting to use a resource before its contents + * has been made locally available. + */ + public static final int NO_LOCAL_CONTENTS = 999; + + ///** + //* Status constant indicating that a classpath entry was invalid + //*/ + //public static final int INVALID_CLASSPATH = 964; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java new file mode 100644 index 00000000000..26648b46920 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICProject.java @@ -0,0 +1,43 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; + +/** + * A C project represents a view of a project resource in terms of C + * elements such as ICFile, ICFolder .... + * CCore.create(project). + *

+ * + * @see CCore#create(org.eclipse.core.resources.IProject) + * @see IBuildEntry + */ +public interface ICProject extends IParent, ICElement { + + /** + * Returns the ICElement corresponding to the given + * path, or null if no such + * ICElement is found. + * + * @exception CModelException if the given path is null + * or absolute + */ + ICElement findElement(IPath path) throws CModelException; + + /** + * Return the ArchiveContainer of this Project. + */ + IArchiveContainer getArchiveContainer(); + + /** + * Return the BinaryContainer of this Project. + */ + IBinaryContainer getBinaryContainer(); + + IProject getProject(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICRoot.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICRoot.java new file mode 100644 index 00000000000..2c44ce1c002 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICRoot.java @@ -0,0 +1,179 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Represent the root C element corresponding to the workspace. + * Since there is only one such root element, it is commonly referred to as + * the C model element. + * The C model element needs to be opened before it can be navigated or manipulated. + * The C model element has no parent (it is the root of the C element + * hierarchy). Its children are ICProjects. + *

+ * This interface provides methods for performing copy, move, rename, and + * delete operations on multiple C elements. + *

+ * + * @see CCore#create(org.eclipse.core.resources.IWorkspaceRoot) + */ +public interface ICRoot extends ICElement, IParent { + /** + * Copies the given elements to the specified container(s). + * If one container is specified, all elements are copied to that + * container. If more than one container is specified, the number of + * elements and containers must match, and each element is copied to + * its associated container. + *

+ * Optionally, each copy can positioned before a sibling + * element. If null is specified for a given sibling, the copy + * is inserted as the last child of its associated container. + *

+ *

+ * Optionally, each copy can be renamed. If + * null is specified for the new name, the copy + * is not renamed. + *

+ *

+ * Optionally, any existing child in the destination container with + * the same name can be replaced by specifying true for + * force. Otherwise an exception is thrown in the event that a name + * collision occurs. + *

+ * + * @param elements the elements to copy + * @param containers the container, or list of containers + * @param siblings the list of siblings element any of which may be + * null; or null + * @param renamings the list of new names any of which may be + * null; or null + * @param replace true if any existing child in a target container + * with the target name should be replaced, and false to throw an + * exception in the event of a name collision + * @param monitor a progress monitor + * @exception CModelException if an element could not be copied. Reasons include: + * + */ + void copy(ICElement[] elements, ICElement[] containers, ICElement[] siblings, String[] renamings, boolean replace, IProgressMonitor monitor) throws CModelException; + /** + * Deletes the given elements, forcing the operation if necessary and specified. + * + * @param elements the elements to delete + * @param force a flag controlling whether underlying resources that are not + * in sync with the local file system will be tolerated + * @param monitor a progress monitor + * @exception CModelException if an element could not be deleted. Reasons include: + * + */ + void delete(ICElement[] elements, boolean force, IProgressMonitor monitor) throws CModelException; + + /** + * Moves the given elements to the specified container(s). + * If one container is specified, all elements are moved to that + * container. If more than one container is specified, the number of + * elements and containers must match, and each element is moved to + * its associated container. + *

+ * Optionally, each element can positioned before a sibling + * element. If null is specified for sibling, the element + * is inserted as the last child of its associated container. + *

+ *

+ * Optionally, each element can be renamed. If + * null is specified for the new name, the element + * is not renamed. + *

+ *

+ * Optionally, any existing child in the destination container with + * the same name can be replaced by specifying true for + * force. Otherwise an exception is thrown in the event that a name + * collision occurs. + *

+ * + * @param elements the elements to move + * @param containers the container, or list of containers + * @param siblings the list of siblings element any of which may be + * null; or null + * @param renamings the list of new names any of which may be + * null; or null + * @param replace true if any existing child in a target container + * with the target name should be replaced, and false to throw an + * exception in the event of a name collision + * @param monitor a progress monitor + * @exception CModelException if an element could not be moved. Reasons include: + * + * + * @exception IllegalArgumentException any element or container is null + */ + void move(ICElement[] elements, ICElement[] containers, ICElement[] siblings, String[] renamings, boolean replace, IProgressMonitor monitor) throws CModelException; + + /** + * Renames the given elements as specified. + * If one container is specified, all elements are renamed within that + * container. If more than one container is specified, the number of + * elements and containers must match, and each element is renamed within + * its associated container. + * + * @param elements the elements to rename + * @param destinations the container, or list of containers + * @param names the list of new names + * @param replace true if an existing child in a target container + * with the target name should be replaced, and false to throw an + * exception in the event of a name collision + * @param monitor a progress monitor + * @exception CModelException if an element could not be renamed. Reasons include: + * + */ + void rename(ICElement[] elements, ICElement[] destinations, String[] names, boolean replace, IProgressMonitor monitor) throws CModelException; + + /** + * Returns the C project with the given name. This is a handle-only method. + * The project may or may not exist. + */ + ICProject getCProject(String name); + + /** + * Returns the C projects. + */ + ICProject[] getCProjects(); + + /** + * Returns the workspace associated with this C model. + */ + IWorkspace getWorkspace(); + + IWorkspaceRoot getRoot(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IElementChangedListener.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IElementChangedListener.java new file mode 100644 index 00000000000..ae43d79e3d9 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IElementChangedListener.java @@ -0,0 +1,20 @@ +package org.eclipse.cdt.core.model; +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * An element changed listener receives notification of changes to C elements + * maintained by the C model. + */ +public interface IElementChangedListener { + + /** + * Notifies that one or more attributes of one or more C elements have changed. + * The specific details of the change are described by the given event. + * + * @param event the change event + */ + public void elementChanged(ElementChangedEvent event); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IEnumeration.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IEnumeration.java new file mode 100644 index 00000000000..0ea78c05c1e --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IEnumeration.java @@ -0,0 +1,12 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * An Enumeration type. + */ +public interface IEnumeration extends IVariable { +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IField.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IField.java new file mode 100644 index 00000000000..f49ebb3c405 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IField.java @@ -0,0 +1,20 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Represents a field(variable) declared in an IStructure(struct, class, union). + */ +public interface IField extends IMember, IVariable { + + /** + * Returns whether this storage specifier is mutable for the member. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + public boolean isMutable() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IFunction.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IFunction.java new file mode 100644 index 00000000000..3b66b6edcf2 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IFunction.java @@ -0,0 +1,78 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represents a function. + */ +public interface IFunction extends ICElement, ISourceReference, ISourceManipulation { + + /** + * Returns the exceptions this method throws, in the order declared in the source. + * or an empty array if this method throws no exceptions. + * + *

For example, a source method declaring "void f(int a) throw (x2, x3);", + * would return the array {"x2", "x3"}. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + */ + public String[] getExceptions() throws CModelException; + + /** + * Returns the number of parameters of this method. + */ + public int getNumberOfParameters(); + + /** + * Returns the initializer of parameters pos for this method. + * Returns an empty string if this argument has no initializer. + * + *

For example, a method declared as void foo(String text, int length=9) + * would return the array {"9"}. + * + * @exception CModelException if this argument does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + public String getParameterInitializer(int pos); + + /** + * Returns the type signatures for the parameters of this method. + * Returns an empty array if this method has no parameters. + * This is a handle-only method. + * + *

For example, a source method declared as void foo(string text, int length) + * would return the array {"string","int"}. + * + * @see Signature + */ + public String[] getParameterTypes(); + + /** + * Returns the type signature of the return value of this method. + * For constructors, this returns the signature for void. + * + *

For example, a source method declared as int getName() + * would return "int". + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + * @see Signature + */ + public String getReturnType() throws CModelException; + + /** + * Returns the access Control of the member. The value can be + * can be examined using class Flags. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @see Flags + */ + public int getAccessControl() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IFunctionDeclaration.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IFunctionDeclaration.java new file mode 100644 index 00000000000..53272f1eff8 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IFunctionDeclaration.java @@ -0,0 +1,80 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represents a function + */ +public interface IFunctionDeclaration extends ICElement, ISourceReference, ISourceManipulation { + + /** + * Returns the type signatures of the exceptions this method throws, + * in the order declared in the source. Returns an empty array + * if this method throws no exceptions. + * + *

For example, a source method declaring "void f(int a) throw (x1, x2);", + * would return the array {"x1", "x2"}. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + * @see Signature + */ + String[] getExceptions() throws CModelException; + + /** + * Returns the number of parameters of this method. + */ + int getNumberOfParameters(); + + /** + * Returns the initializer of parameters position for this method. + * Returns an empty string if this argument has no initializer. + * + *

For example, a method declared as public void foo(String text, int length=9) + * would return the array {"9"}. + * + * @exception CModelException if this argument does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + String getParameterInitializer(int pos); + + /** + * Returns the type signatures for the parameters of this method. + * Returns an empty array if this method has no parameters. + * This is a handle-only method. + * + *

For example, a source method declared as void foo(string text, int length) + * would return the array {"string","int"}. + * + * @see Signature + */ + String[] getParameterTypes(); + + /** + * Returns the type signature of the return value of this method. + * For constructors, this returns the signature for void. + * + *

For example, a source method declared as public String getName() + * would return "String". + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + * @see Signature + */ + String getReturnType() throws CModelException; + + /** + * Returns the access Control of the member. The access qualifier + * can be examine using the AccessControl class. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @see IAccessControl + */ + int getAccessControl() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java new file mode 100644 index 00000000000..e6e22ecc7c9 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInclude.java @@ -0,0 +1,25 @@ +package org.eclipse.cdt.core.model; +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represents an include declaration in a C translation unit. + */ +public interface IInclude extends ICElement, ISourceReference, ISourceManipulation { + /** + * Returns the name that of the included file. + * For example, for the statement "#include , + * this returns "stdio.h". + */ + String getIncludeName(); + + /** + * Returns whether the included was search on "standard places" like /usr/include first . + * An include is standard if it starts with "\<". + * For example, "#include \" returns true and + * "#include "foobar.h" returns false. + */ + boolean isStandard(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInheritance.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInheritance.java new file mode 100644 index 00000000000..ae8f968cda3 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IInheritance.java @@ -0,0 +1,21 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Place holder of the inherited class from struct or class(IStructure). + */ +public interface IInheritance { + /** + * Return the inherited structures. + */ + public IStructure [] getBaseTypes() throws CModelException; + + /** + * Return the access control for each inherited structure. + */ + public int getAccessControl(int pos) throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILibraryReference.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILibraryReference.java new file mode 100644 index 00000000000..43c12887f82 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ILibraryReference.java @@ -0,0 +1,11 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + */ +public interface ILibraryReference extends IParent, ICElement { +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMacro.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMacro.java new file mode 100644 index 00000000000..6c6445347ee --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMacro.java @@ -0,0 +1,14 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Represents a field declared in a type. + */ +public interface IMacro extends ICElement, ISourceManipulation, ISourceReference { + String getIdentifierList(); + String getTokenSequence(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMember.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMember.java new file mode 100644 index 00000000000..a0667250b8c --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMember.java @@ -0,0 +1,48 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Common protocol for C elements that can be members of types. + * This set consists of IType, IMethod, + * IField. + */ +public interface IMember extends ICElement, ISourceReference, ISourceManipulation { + + ///** + //* Returns the structure in which this member is declared, or null + //* if this member is not declared in a type (for example, a top-level type). + //*/ + //IStructure belongsTo() throws CModelException; + + /** + * Returns true if the member as class scope. + * For example static methods in C++ have class scope + * + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + public boolean hasClassScope() throws CModelException; + + /** + * Returns whether this method/field is declared constant. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + public boolean isConst() throws CModelException; + + /** + * Returns the access Control of the member. The access qualifier + * can be examine using the AccessControl class. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * @see IAccessControl + */ + public int getAccessControl() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMethod.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMethod.java new file mode 100644 index 00000000000..196287c1f4c --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMethod.java @@ -0,0 +1,117 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represents the definition method of a class. + */ +public interface IMethod extends IMember { + + /** + * Returns the type signatures of the exceptions this method throws, + * in the order declared in the source. Returns an empty array + * if this method throws no exceptions. + * + *

For example, a source method declaring "throws IOException", + * would return the array {"QIOException;"}. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + * @see Signature + */ + String[] getExceptions() throws CModelException; + + /** + * Returns the number of parameters of this method. + */ + int getNumberOfParameters(); + + /** + * Returns the initializer of parameters pos for this method. + * Returns an empty string if this argument has no initializer. + * + *

For example, a method declared as public void foo(String text, int length=9) + * would return the array {"9"}. + * + * @exception CModelException if this argument does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + String getParameterInitializer(int pos); + + /** + * Returns the type signatures for the parameters of this method. + * Returns an empty array if this method has no parameters. + * This is a handle-only method. + * + *

For example, a source method declared as void foo(String text, int length) + * would return the array {"String","int"}. + * + * @see Signature + */ + String[] getParameterTypes(); + + /** + * Returns the type signature of the return value of this method. + * For constructors, this returns the signature for void. + * + *

For example, a source method declared as public String getName() + * would return "String". + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + * @see Signature + */ + String getReturnType() throws CModelException; + + /** + * Returns whether this method is a constructor. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isConstructor() throws CModelException; + + /** + * Returns whether this method is a destructor. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isDestructor() throws CModelException; + + /** + * Returns whether this method is an operator method. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isOperator() throws CModelException; + + /** + * Returns whether this method is declared pure virtual. + * + *

For example, a source method declared as virtual void m() = 0;. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isAbstract() throws CModelException; + + /** + * Returns whether this method is declared virtual. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isVirtual() throws CModelException; + + /** + * return true if the member is a friend. + */ + public boolean isFriend() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMethodDeclaration.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMethodDeclaration.java new file mode 100644 index 00000000000..9a2fac2bf45 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IMethodDeclaration.java @@ -0,0 +1,117 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represents the declaration method of a class + */ +public interface IMethodDeclaration extends IMember { + + /** + * Returns the type signatures of the exceptions this method throws, + * in the order declared in the source. Returns an empty array + * if this method throws no exceptions. + * + *

For example, a source method declaring "throws IOException", + * would return the array {"QIOException;"}. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + * @see Signature + */ + String[] getExceptions() throws CModelException; + + /** + * Returns the number of parameters of this method. + */ + int getNumberOfParameters(); + + /** + * Returns the initializer of parameters pos for this method. + * Returns an empty string if this argument has no initializer. + * + *

For example, a method declared as public void foo(String text, int length=9) + * would return the array {"9"}. + * + * @exception CModelException if this argument does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + String getParameterInitializer(int pos); + + /** + * Returns the type signatures for the parameters of this method. + * Returns an empty array if this method has no parameters. + * This is a handle-only method. + * + *

For example, a source method declared as void foo(String text, int length) + * would return the array {"String","int"}. + * + * @see Signature + */ + String[] getParameterTypes(); + + /** + * Returns the type signature of the return value of this method. + * For constructors, this returns the signature for void. + * + *

For example, a source method declared as public String getName() + * would return "String". + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + * + * @see Signature + */ + String getReturnType() throws CModelException; + + /** + * Returns whether this method is a constructor. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isConstructor() throws CModelException; + + /** + * Returns whether this method is a destructor. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isDestructor() throws CModelException; + + /** + * Returns whether this method is an operator method. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isOperator() throws CModelException; + + /** + * Returns whether this method is declared pure virtual. + * + *

For example, a source method declared as virtual void m() = 0;. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isAbstract() throws CModelException; + + /** + * Returns whether this method is declared virtual. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource. + */ + boolean isVirtual() throws CModelException; + + /** + * return true if the member is a friend. + */ + public boolean isFriend() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/INamespace.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/INamespace.java new file mode 100644 index 00000000000..e43b046cedd --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/INamespace.java @@ -0,0 +1,16 @@ +package org.eclipse.cdt.core.model; +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Represents a package declaration in a C translation unit. + */ +public interface INamespace extends ICElement, ISourceManipulation, ISourceReference { + /** + * Returns the name of the package the statement refers to. + * This is a handle-only method. + */ + String getElementName(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IParent.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IParent.java new file mode 100644 index 00000000000..a31077e022f --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IParent.java @@ -0,0 +1,31 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Common protocol for C elements that contain other C elements. + */ +public interface IParent { + + /** + * Returns the immediate children of this element. + * The children are in no particular order. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + ICElement[] getChildren(); //throws CModelException; + + /** + * Returns whether this element has one or more immediate children. + * This is a convenience method, and may be more efficient than + * testing whether getChildren is an empty array. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + boolean hasChildren(); //throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceManipulation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceManipulation.java new file mode 100644 index 00000000000..2cf3f0b2870 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceManipulation.java @@ -0,0 +1,109 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Common protocol for C elements that support source code manipulations such + * as copy, move, rename, and delete. + */ +public interface ISourceManipulation { + /** + * Copies this element to the given container. + * + * @param container the container + * @param sibling the sibling element before which the copy should be inserted, + * or null if the copy should be inserted as the last child of + * the container + * @param rename the new name for the element, or null if the copy + * retains the name of this element + * @param replace true if any existing child in the container with + * the target name should be replaced, and false to throw an + * exception in the event of a name collision + * @param monitor a progress monitor + * @exception CModelException if this element could not be copied. Reasons include: + *

+ * + * @exception IllegalArgumentException if container is null + */ + void copy(ICElement container, ICElement sibling, String rename, boolean replace, IProgressMonitor monitor) throws CModelException; + + /** + * Deletes this element, forcing if specified and necessary. + * + * @param force a flag controlling whether underlying resources that are not + * in sync with the local file system will be tolerated (same as the force flag + * in IResource operations). + * @param monitor a progress monitor + * @exception CModelException if this element could not be deleted. Reasons include: + * + */ + void delete(boolean force, IProgressMonitor monitor) throws CModelException; + + /** + * Moves this element to the given container. + * + * @param container the container + * @param sibling the sibling element before which the element should be inserted, + * or null if the element should be inserted as the last child of + * the container + * @param rename the new name for the element, or null if the + * element retains its name + * @param replace true if any existing child in the container with + * the target name should be replaced, and false to throw an + * exception in the event of a name collision + * @param monitor a progress monitor + * @exception CModelException if this element could not be moved. Reasons include: + * + * + * @exception IllegalArgumentException if container is null + */ + + void move(ICElement container, ICElement sibling, String rename, boolean replace, IProgressMonitor monitor) throws CModelException; + + /** + * Renames this element to the given name. + * + * @param name the new name for the element + * @param replace true if any existing element with the target name + * should be replaced, and false to throw an exception in the + * event of a name collision + * @param monitor a progress monitor + * @exception CModelException if this element could not be renamed. Reasons include: + * + */ + void rename(String name, boolean replace, IProgressMonitor monitor) throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceRange.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceRange.java new file mode 100644 index 00000000000..d5d2d752f0a --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceRange.java @@ -0,0 +1,42 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * A source range defines an element's source coordinates + */ +public interface ISourceRange { + + /** + * Returns the 0-based starting position of this element. + */ + public int getStartPos(); + + /** + * Returns the number of characters of the source code for this element. + */ + public int getLength(); + + /** + * Returns the Id starting position of this element. + */ + public int getIdStartPos(); + + /** + * Returns the number of characters of the Id for this element. + */ + public int getIdLength(); + + /** + * Returns the 1-based starting line of this element. + */ + public int getStartLine(); + + /** + * Returns the 1-based ending line of this element. + */ + public int getEndLine(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java new file mode 100644 index 00000000000..daa5f1f21ee --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ISourceReference.java @@ -0,0 +1,51 @@ +package org.eclipse.cdt.core.model; +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Common protocol for C elements that have associated source code. + *

+ * Note: For IBinary, IArchive and other members + * derived from a binary type, the implementation returns source iff the + * element has attached source code and debuging information. + * + */ + +public interface ISourceReference { + + /** + * Returns the source code associated with this element. + *

+ * For binary files, this returns the source of the entire translation unit + * associated with the binary file (if there is one). + *

+ * + * @return the source code, or null if this element has no + * associated source code + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + String getSource() throws CModelException; + + /** + * Returns the source range associated with this element. + *

+ * For binary files, this returns the range of the entire translation unit + * associated with the binary file (if there is one). + *

+ * + * @return the source range, or null if if this element has no + * associated source code + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + ISourceRange getSourceRange() throws CModelException; + + /** + * Returns the translation unit in which this member is declared, or null + * if this member is not declared in a translation unit (for example, a binary type). + */ + ITranslationUnit getTranslationUnit(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IStructure.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IStructure.java new file mode 100644 index 00000000000..c0cacfe885d --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IStructure.java @@ -0,0 +1,27 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +/** + * Represent struct(ure), class or union. + */ +public interface IStructure extends IInheritance, IParent, ICElement, IVariable { + //public String instantiatesTemplate(); + + public IField getField(String name); + public IField[] getFields(); + + public IMethod getMethod(String name); + public IMethod [] getMethods(); + + public boolean isUnion(); + + public boolean isClass(); + + public boolean isStruct(); + + public boolean isAbstract(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java new file mode 100644 index 00000000000..888fcb3b55e --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITranslationUnit.java @@ -0,0 +1,120 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Represents an entire C translation unit (.c source file). + * The children are of type IStructureElement, + * IInclude, etc.. + * and appear in the order in which they are declared in the source. + * If a .c file cannot be parsed, its structure remains unknown. + * Use ICElement.isStructureKnown to determine whether this is + * the case. + */ +public interface ITranslationUnit extends ICFile , ISourceReference, ISourceManipulation { + /** + * Creates and returns an include declaration in this translation unit + * with the given name. + *

+ * Optionally, the new element can be positioned before the specified + * sibling. If no sibling is specified, the element will be inserted + * as the last import declaration in this translation unit. + *

+ * If the translation unit already includes the specified include declaration, + * the import is not generated (it does not generate duplicates). + * + * @param name the name of the include declaration to add (For example: "stdio.h" or + * "sys/types.h") + * @param sibling the existing element which the include declaration will be inserted immediately before (if + * null , then this include will be inserted as the last include declaration. + * @param monitor the progress monitor to notify + * @return the newly inserted include declaration (or the previously existing one in case attempting to create a duplicate) + * + * @exception CModelException if the element could not be created. Reasons include: + *

+ */ + IInclude createInclude(String name, ICElement sibling, IProgressMonitor monitor) throws CModelException; + + /** + * Creates and returns a namesapce declaration in this translation unit + * with the given package name. + * + *

If the translation unit already includes the specified package declaration, + * it is not generated (it does not generate duplicates). + * + * @param name the name of the namespace declaration to add (For example, "std") + * @param monitor the progress monitor to notify + * @return the newly inserted namespace declaration (or the previously existing one in case attempting to create a duplicate) + * + * @exception CModelException if the element could not be created. Reasons include: + *

+ */ + IUsing createUsing (String name, IProgressMonitor monitor) throws CModelException; + + /** + * Returns the smallest element within this translation unit that + * includes the given source position (that is, a method, field, etc.), or + * null if there is no element other than the translation + * unit itself at the given position, or if the given position is not + * within the source range of this translation unit. + * + * @param position a source position inside the translation unit + * @return the innermost C element enclosing a given source position or null + * if none (excluding the translation unit). + * @exception CModelException if the translation unit does not exist or if an + * exception occurs while accessing its corresponding resource + */ + ICElement getElementAtLine(int line) throws CModelException; + + ICElement getElement(String name) throws CModelException; + + /** + * Returns the include declaration in this translation unit with the given name. + * + * @param the name of the include to find (For example: "stdio.h" + * or "sys/types.h") + * @return a handle onto the corresponding include declaration. The include declaration may or may not exist. + */ + IInclude getInclude(String name) ; + + /** + * Returns the include declarations in this translation unit + * in the order in which they appear in the source. + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + IInclude[] getIncludes() throws CModelException; + + /** + * Returns the first namespace declaration in this translation unit with the given package name + * This is a handle-only method. The namespace declaration may or may not exist. + * + * @param name the name of the namespace declaration (For example, "std") + */ + IUsing getUsing(String name); + + /** + * Returns the namespace declarations in this translation unit + * in the order in which they appear in the source. + * + * @return an array of namespace declaration (normally of size one) + * + * @exception CModelException if this element does not exist or if an + * exception occurs while accessing its corresponding resource + */ + IUsing[] getUsings() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITypeDef.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITypeDef.java new file mode 100644 index 00000000000..eae2e26fbcc --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ITypeDef.java @@ -0,0 +1,16 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Represents a field declared in a type. + */ +public interface ITypeDef extends ICElement, ISourceManipulation, ISourceReference { + /** + * Return the type beeing alias. + */ + String getType() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IUsing.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IUsing.java new file mode 100644 index 00000000000..2002f55a0e0 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IUsing.java @@ -0,0 +1,16 @@ +package org.eclipse.cdt.core.model; +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Represents a "using" declaration in C translation unit. + */ +public interface IUsing extends ICElement, ISourceManipulation, ISourceReference { + /** + * Returns the name of the package the statement refers to. + * This is a handle-only method. + */ + String getElementName(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariable.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariable.java new file mode 100644 index 00000000000..5708996a27d --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariable.java @@ -0,0 +1,15 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Represents a global variable. + */ +public interface IVariable extends ICElement , ISourceManipulation, ISourceReference { + public String getType(); + public String getInitializer(); + public int getAccessControl() throws CModelException; +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariableDeclaration.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariableDeclaration.java new file mode 100644 index 00000000000..ea79d61beb8 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariableDeclaration.java @@ -0,0 +1,15 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Represents the declaration of a variable. + */ +public interface IVariableDeclaration extends ICElement, ISourceManipulation, ISourceReference { + + public String getType (); + public int getAccesControl(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariableLocal.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariableLocal.java new file mode 100644 index 00000000000..f88ee6452d6 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IVariableLocal.java @@ -0,0 +1,12 @@ +package org.eclipse.cdt.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * Represents a static variable. + */ +public interface IVariableLocal extends IVariable { +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Archive.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Archive.java new file mode 100644 index 00000000000..14a515fdf98 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Archive.java @@ -0,0 +1,44 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.resources.IFile; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IArchive; +import org.eclipse.cdt.core.model.IBinary; + +public class Archive extends CFile implements IArchive { + + public Archive(ICElement parent, IFile file) { + super(parent, file); + } + + public Archive(ICElement parent, IPath path) { + super (parent, path); + } + + public boolean isReadOnly() { + return true; + } + + public boolean isArchive() { + return true; + } + + public IBinary[] getBinaries() { + return (IBinary[])getChildren(); + } + + public CElementInfo createElementInfo() { + return new ArchiveInfo(this); + } + + protected ArchiveInfo getArchiveInfo() { + return (ArchiveInfo)getElementInfo(); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java new file mode 100644 index 00000000000..ad1261403a6 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveContainer.java @@ -0,0 +1,87 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; + +import org.eclipse.cdt.core.model.IArchive; +import org.eclipse.cdt.core.model.IArchiveContainer; +import org.eclipse.cdt.core.model.ICElement; + +public class ArchiveContainer extends Parent implements IArchiveContainer { + + CProject cProject; + private long modificationStamp; + + public ArchiveContainer (CProject cProject) { + super (cProject, null, "lib", CElement.C_CONTAINER); + this.cProject = cProject; + IProject project = cProject.getProject(); + IFolder folder = project.getFolder("Virtual.lib"); + setUnderlyingResource(folder); + } + + public IArchive[] getArchives() { + ICElement[] e = getChildren(false); + IArchive[] a = new IArchive[e.length]; + System.arraycopy(e, 0, a, 0, e.length); + return a; + } + + public boolean hasChildren() { + return (getChildren().length > 0); + } + + public ICElement [] getChildren() { + return getChildren(true); + } + + public ICElement [] getChildren(boolean sync) { + if (!cProject.hasRunElf()) { + // It is vital to set this to true first, if not we are going to loop + cProject.setRunElf(true); + ElfRunner runner = new ElfRunner(cProject); + Thread thread = new Thread(runner, "Archive Runner"); + // thread.setPriority(Thread.NORM_PRIORITY - 1); + thread.setDaemon(true); + thread.start(); + if (sync) { + try { + thread.join(); + } catch (InterruptedException e) { + } + } + } + return super.getChildren(); + } + + //public IResource getUnderlyingResource() { + // return null; + //} + + public IResource getCorrespondingResource() { + return null; + } + + void addChildIfLib(IFile file) { + CModelManager factory = CModelManager.getDefault(); + if (factory.isArchive(file)) { + ICElement celement = factory.create(file); + if (celement != null) { + if (celement instanceof IArchive) { + addChild (celement); + } + } + } + } + + public CElementInfo createElementInfo() { + return new CElementInfo(this); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveInfo.java new file mode 100644 index 00000000000..3aac72d6fbf --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/ArchiveInfo.java @@ -0,0 +1,77 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.io.IOException; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IPath; + +import org.eclipse.cdt.core.model.ICElement; + +import org.eclipse.cdt.utils.elf.AR; +import org.eclipse.cdt.utils.elf.ElfHelper; + +/** + * Info for ICProject. + */ + +class ArchiveInfo extends CFileInfo { + + /** + */ + public ArchiveInfo(CElement element) { + super(element); + } + + public ICElement [] getChildren() { + init(); + return super.getChildren(); + } + + public void init() { + if (hasChanged()) { + removeChildren(); + loadInfo(); + } + } + + public boolean isArchive() { + return true; + } + + protected void loadInfo() { + IPath location = ((CFile)getElement()).getLocation(); + IFile file = ((CFile)getElement()).getFile(); + try { + AR ar = new AR(location.toOSString()); + AR.ARHeader[] header = ar.getHeaders(); + for (int i = 0; i < header.length; i++) { + ElfHelper helper = new ElfHelper(header[i].getElf()); + //IPath path = new Path(header[i].getObjectName()); + // FIXME: We should create a special IResource for this files + // but for now, just bypass. + Binary binary = new Binary(getElement(), file, header[i].getObjectName()) { + public IResource getCorrespondingResource() { + return null; + } + }; + // Force the loading so we can dispose; + ((BinaryInfo)(binary.getElementInfo())).elfHelper = helper; + // Force the loading of the chidren right away so we can + // dispose of the elf Elper. + binary.getChildren(); + ((BinaryInfo)(binary.getElementInfo())).elfHelper = null; + helper.dispose(); + addChild(binary); + } + ar.dispose(); + } catch (IOException e) { + //e.printStackTrace(); + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java new file mode 100644 index 00000000000..f0bb5fe6884 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Binary.java @@ -0,0 +1,80 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.resources.IFile; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IBinary; + +public class Binary extends CFile implements IBinary { + + public Binary(ICElement parent, IFile file) { + super(parent, file); + } + + public Binary(ICElement parent, IPath path) { + super (parent, path); + } + + public Binary(ICElement parent, IFile file, String name) { + super(parent, file, name); + } + + + public boolean isReadOnly () { + return true; + } + + public boolean isBinary() { + return true; + } + + public boolean hasDebug () { + return ((BinaryInfo)getElementInfo()).hasDebug(); + } + + public boolean isExecutable() { + return ((BinaryInfo)getElementInfo()).isExecutable(); + } + + public boolean isObject() { + return ((BinaryInfo)getElementInfo()).isObject(); + } + + public boolean isSharedLib() { + return ((BinaryInfo)getElementInfo()).isSharedLib(); + } + + public String [] getNeededSharedLibs() { + return ((BinaryInfo)getElementInfo()).getNeededSharedLibs(); + } + + public String getCPU() { + return ((BinaryInfo)getElementInfo()).getCPU(); + } + + public long getText() { + return ((BinaryInfo)getElementInfo()).getText(); + } + + public long getData() { + return ((BinaryInfo)getElementInfo()).getData(); + } + + public long getBSS() { + return ((BinaryInfo)getElementInfo()).getBSS(); + } + + public String getSoname() { + return ((BinaryInfo)getElementInfo()).getSoname(); + } + + public CElementInfo createElementInfo() { + return new BinaryInfo(this); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryContainer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryContainer.java new file mode 100644 index 00000000000..02962288bcb --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryContainer.java @@ -0,0 +1,147 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceVisitor; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.IBinaryContainer; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICRoot; + +public class BinaryContainer extends Parent implements IBinaryContainer { + + CProject cProject; + private long modificationStamp; + + public BinaryContainer (CProject cProject) { + this (cProject, "bin"); + } + + public BinaryContainer (CProject cProject, String name) { + super (cProject, null, name, CElement.C_CONTAINER); + this.cProject = cProject; + IProject project = cProject.getProject(); + IFolder folder = project.getFolder("Virtual.bin"); + setUnderlyingResource(folder); + } + + public IBinary[] getBinaries() { + ICElement[] e = getChildren(false); + IBinary[] b = new IBinary[e.length]; + System.arraycopy(e, 0, b, 0, e.length); + return b; + } + + public boolean hasChildren() { + return (getChildren().length > 0); + } + + public ICElement [] getChildren() { + return getChildren(true); + } + + public ICElement [] getChildren(boolean sync) { + // The first time probe the entire project to discover binaries. + if (!cProject.hasRunElf()) { + cProject.setRunElf(true); + ElfRunner runner = new ElfRunner(cProject); + Thread thread = new Thread(runner, "Elf Runner"); + // thread.setPriority(Thread.NORM_PRIORITY - 1); + thread.setDaemon(true); + thread.start(); + if (sync) { + try { + thread.join(); + } catch (InterruptedException e) { + } + } + } + return super.getChildren(); + } + + public IResource getCorrespondingResource() { + return null; + } + + //public IResource getUnderlyingResource() { + // return null; + //} + + void addChildIfExec(CoreModel factory, IFile file) { + // Attempt to speed things up by rejecting up front + // Things we know should not be Elf/Binary files. + if (!factory.isTranslationUnit(file)) { + ICElement celement = factory.create(file); + if (celement != null) { + if (celement instanceof IBinary) { + IBinary bin = (IBinary)celement; + if (bin.isExecutable() || bin.isSharedLib()) { + addChild (bin); + } + } + } + } + } + + public CElementInfo createElementInfo() { + return new CElementInfo(this); + } + + class Visitor implements IResourceVisitor { + CoreModel factory = CoreModel.getDefault(); + BinaryContainer cbin; + + public Visitor (BinaryContainer element) { + cbin = element; + } + + public boolean visit(IResource res) throws CoreException { + if (res instanceof IFile) { + cbin.addChildIfExec(factory, (IFile)res); + return false; + } + return true; + } + } + + class BinaryRunnable implements Runnable { + BinaryContainer cbin; + + public BinaryRunnable(BinaryContainer element) { + cbin = element; + } + + public void run() { + try { + ((IProject)cbin.getCProject().getUnderlyingResource()).accept(new Visitor(cbin)); + } catch (CoreException e) { + //e.printStackTrace(); + } + // Fired the event. + ICElement[] children = cbin.getChildren(); + if (children.length > 0) { + CModelManager factory = CModelManager.getDefault(); + ICElement root = (ICRoot)factory.getCRoot(); + CElementDelta cdelta = new CElementDelta(root); + cdelta.added(cbin.getCProject()); + cdelta.added(cbin); + for (int i = 0; i < children.length; i++) { + ICElement child = children[i]; + cdelta.added(child); + } + factory.registerCModelDelta(cdelta); + factory.fire(); + } + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryInfo.java new file mode 100644 index 00000000000..b47cacafeab --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/BinaryInfo.java @@ -0,0 +1,253 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +import org.eclipse.cdt.core.model.ICElement; + +import org.eclipse.cdt.utils.elf.Elf; +import org.eclipse.cdt.utils.elf.ElfHelper; + +class BinaryInfo extends CFileInfo { + + String [] needed; + ElfHelper.Sizes sizes; + Elf.Attribute attribute; + String soname; + Map hash; + ElfHelper elfHelper = null; + + public BinaryInfo(CElement element) { + super(element); + needed = new String[0]; + sizes = null; + attribute = null; + soname = ""; + hash = new HashMap(); + } + + public boolean isBinary() { + return true; + } + + public ICElement [] getChildren() { + initChildren(); + return super.getChildren(); + } + + public String getCPU() { + init(); + String cpu = null; + if (attribute != null) + cpu = attribute.getCPU(); + return (cpu == null) ? "" : cpu; + } + + public boolean isSharedLib() { + init(); + if (attribute != null) + return attribute.getType() == attribute.ELF_TYPE_SHLIB; + return false; + } + + public boolean isExecutable() { + init(); + if (attribute != null) + return attribute.getType() == attribute.ELF_TYPE_EXE; + return false; + } + + public boolean isObject() { + init(); + if (attribute != null) + return attribute.getType() == attribute.ELF_TYPE_OBJ; + return false; + } + + public boolean hasDebug () { + init(); + if (attribute != null) + return attribute.hasDebug(); + return false; + } + + public String [] getNeededSharedLibs() { + init(); + return needed; + } + + public long getText() { + init(); + if (sizes != null) { + return sizes.text; + } + return 0; + } + + public long getData() { + init(); + if (sizes != null) { + return sizes.data; + } + return 0; + } + + public long getBSS() { + init(); + if (sizes != null) { + return sizes.bss; + } + return 0; + } + + public String getSoname() { + init(); + return soname; + } + + private void addFunction(Elf.Symbol [] symbol, boolean external) { + for (int i = 0; i < symbol.length; i++) { + ICElement parent = getElement(); + String filename = null; + try { + filename = symbol[i].getFilename(); + } catch (IOException e) { + //e.printStackTrace(); + } + Function function = null; + + // Addr2line returns the funny "??" when it can find the file. + if (filename != null && !filename.equals("??")) { + TranslationUnit tu = null; + IPath path = new Path(filename); + if (hash.containsKey(path)) { + tu = (TranslationUnit)hash.get(path); + } else { + tu = new TranslationUnit(parent, path); + hash.put(path, tu); + addChild(tu); + } + function = new Function(tu, symbol[i].toString()); + tu.addChild(function); + } else { + function = new Function(parent, symbol[i].toString()); + addChild(function); + } + if (function != null) + if (!external) + function.getFunctionInfo().setAccessControl(IConstants.AccStatic); + } + } + + private void addVariable(Elf.Symbol[] symbol, boolean external) { + for (int i = 0; i < symbol.length; i++) { + String filename = null; + try { + filename = symbol[i].getFilename(); + } catch (IOException e) { + //e.printStackTrace(); + } + ICElement parent = getElement(); + Variable variable = null; + // Addr2line returns the funny "??" when it can not find the file. + if (filename != null && !filename.equals("??")) { + TranslationUnit tu = null; + IPath path = new Path(filename); + if (hash.containsKey(path)) { + tu = (TranslationUnit)hash.get(path); + } else { + tu = new TranslationUnit(parent, path); + hash.put(path, tu); + addChild(tu); + } + variable = new Variable(tu, symbol[i].toString()); + tu.addChild(variable); + } else { + variable = new Variable(parent, symbol[i].toString()); + addChild(variable); + } + if (variable != null) + if (!external) + variable.getVariableInfo().setAccessControl(IConstants.AccStatic); + } + } + + protected void init() { + if (hasChanged()) { + loadInfo(); + } + } + + protected void initChildren() { + if (hasChanged() || !isStructureKnown()) { + removeChildren(); + loadInfoChildren(); + } + } + + + protected ElfHelper getElfHelper() throws IOException { + if (elfHelper != null) { + return elfHelper; + } + CFile file = (CFile)getElement(); + if (file != null) { + IPath path = ((CFile)getElement()).getLocation(); + if (path == null) + path = new Path(""); + return new ElfHelper(path.toOSString()); + } + throw new IOException("No file assiocated with Binary"); + } + + protected void loadInfo() { + try { + ElfHelper helper = this.getElfHelper(); + Elf.Dynamic[] sharedlibs = helper.getNeeded(); + needed = new String[sharedlibs.length]; + for (int i = 0; i < sharedlibs.length; i++) { + needed[i] = sharedlibs[i].toString(); + } + + sizes = helper.getSizes(); + soname = helper.getSoname(); + attribute = helper.getElf().getAttributes(); + helper.dispose(); + } catch (IOException e) { + //e.printStackTrace(); + } + } + + protected void loadInfoChildren() { + try { + setIsStructureKnown(true); + ElfHelper helper = this.getElfHelper(); + addFunction(helper.getExternalFunctions(), true); + addFunction(helper.getLocalFunctions(), false); + addVariable(helper.getExternalObjects(), true); + addVariable(helper.getLocalObjects(), false); + + Elf.Dynamic[] sharedlibs = helper.getNeeded(); + needed = new String[sharedlibs.length]; + for (int i = 0; i < sharedlibs.length; i++) { + needed[i] = sharedlibs[i].toString(); + } + + sizes = helper.getSizes(); + soname = helper.getSoname(); + attribute = helper.getElf().getAttributes(); + helper.dispose(); + } catch (IOException e) { + //e.printStackTrace(); + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java new file mode 100644 index 00000000000..c66ebbe2ebc --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElement.java @@ -0,0 +1,267 @@ +package org.eclipse.cdt.internal.core.model; +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.core.runtime.IPath; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICRoot; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.CModelException; + +public abstract class CElement extends PlatformObject implements ICElement { + + protected int fType; + + protected ICElement fParent; + + protected CElementInfo fCElementInfo; + + protected String fName; + + protected int fStartPos; + protected int fLength; + protected int fIdStartPos; + protected int fIdLength; + protected int fStartLine; + protected int fEndLine; + + protected CElement[] empty = new CElement[0]; + + protected CElement(ICElement parent, String name, int type) { + fParent= parent; + fName= name; + fType= type; + fCElementInfo = null; + } + + // setters + + public void setElementType (int type) { + fType= type; + } + + public void setElementName(String name) { + fName = name; + } + + public void setParent (ICElement parent) { + fParent = parent; + } + + // getters + + public int getElementType() { + return fType; + } + + public String getElementName() { + return fName; + } + + public ICElement getParent() { + return fParent; + } + + public IPath getPath() { + try { + IResource res = getUnderlyingResource(); + if (res != null) + return res.getFullPath(); + } catch (CModelException e) { + e.printStackTrace(); + } + return null; + } + + public boolean exists() { + try { + return getCorrespondingResource() != null; + } catch (CModelException e) { + e.printStackTrace(); + } + return false; + } + + public boolean isReadOnly () { + return true; + } + + public boolean isStructureKnown() throws CModelException { + return getElementInfo().isStructureKnown(); + } + + public ICRoot getCRoot () { + return getParent().getCRoot(); + } + + public ICProject getCProject() { + return getParent().getCProject(); + } + + protected void addChild(ICElement e) { + } + + public void setPos(int startPos, int length) { + fStartPos = startPos; + fLength = length; + } + + public int getStartPos() { + return fStartPos; + } + + public int getLength() { + return fLength; + } + + public void setIdPos(int startPos, int length) { + fIdStartPos= startPos; + fIdLength= length; + } + + public int getIdStartPos() { + return fIdStartPos; + } + + public int getIdLength() { + return fIdLength; + } + + public int getStartLine() { + return fStartLine; + } + + public int getEndLine() { + return fEndLine; + } + + public void setLines(int startLine, int endLine) { + fStartLine = startLine; + fEndLine = endLine; + } + + + public abstract IResource getUnderlyingResource() throws CModelException; + + public abstract IResource getCorrespondingResource() throws CModelException; + + protected abstract CElementInfo createElementInfo(); + + /** + * Finds a member corresponding to a give element. + */ + //public ICElement findEqualMember(ICElement elem) { + // if (this instanceof IParent) { + // ICElement[] members = ((IParent)this).getChildren(); + // if (members != null) { + // for (int i= members.length - 1; i >= 0; i--) { + // ICElement curr= members[i]; + // if (curr.equals(elem)) { + // return curr; + // } else { + // ICElement res= curr.findEqualMember(elem); + // if (res != null) { + // return res; + // } + // } + // } + // } + // return null; + //} + + /** + * Tests if an element has the same name, type and an equal parent. + */ + public boolean equals (Object o) { + if (this == o) + return true; + if (o instanceof CElement) { + CElement other = (CElement) o; + try { + IResource tres = getCorrespondingResource(); + IResource ores = other.getCorrespondingResource(); + if (ores != null && tres != null) { + return tres.equals(ores); + } + } catch (CModelException e) { + //e.printStackTrace(); + } + if (fType != other.fType) + return false; + if (fName.equals(other.fName)) { + if (fParent != null && fParent.equals(other.fParent)) { + return true; + } + if (fParent == null && other.fParent == null) + return true; + } + } + return false; + } + + public CElementInfo getElementInfo () { + if (fCElementInfo == null) { + fCElementInfo = createElementInfo(); + } + return fCElementInfo; + } + + public String toString() { + return getElementName(); + } + + public String toDebugString() { + return getElementName() + " " + getTypeString(getElementType()); + } + + // util + public static String getTypeString(int type) { + switch (type) { + case C_ROOT: + return "CROOT"; + case C_PROJECT: + return "CPROJECT"; + case C_FOLDER: + return "CFOLDER"; + case C_FILE: + return "CFILE"; + case C_FUNCTION: + return "C_FUNCTION"; + case C_FUNCTION_DECLARATION: + return "C_FUNCTION_DECLARATION"; + case C_VARIABLE: + return "C_VARIABLE"; + case C_VARIABLE_DECLARATION: + return "C_VARIABLE_DECLARATION"; + case C_INCLUDE: + return "C_INCLUDE"; + case C_MACRO: + return "C_MACRO"; + case C_STRUCT: + return "C_STRUCT"; + case C_CLASS: + return "C_CLASS"; + case C_UNION: + return "C_UNION"; + case C_FIELD: + return "C_FIELD"; + case C_METHOD: + return "C_METHOD"; + default: + return "UNKNOWN"; + } + } + + /** + * Runs a C Model Operation + */ + protected void runOperation(CModelOperation operation, IProgressMonitor monitor) throws CModelException { + CModelManager.getDefault().runOperation(operation, monitor); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementDelta.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementDelta.java new file mode 100644 index 00000000000..ad99aaa2e2f --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementDelta.java @@ -0,0 +1,736 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +import java.util.ArrayList; + +import org.eclipse.core.resources.IResourceDelta; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.IArchive; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.CModelException; + + +/** + * @see ICElementDelta + */ +public class CElementDelta implements ICElementDelta { + /** + * The element that this delta describes the change to. + * @see #getElement() + */ + protected ICElement fChangedElement; + + /** + * @see #getKind() + */ + private int fKind = 0; + + /** + * @see #getFlags() + */ + private int fChangeFlags = 0; + + /** + * @see #getMovedFromHandle() + */ + protected ICElement fMovedFromHandle = null; + + /** + * @see #getMovedToHandle() + */ + protected ICElement fMovedToHandle = null; + + /** + * Collection of resource deltas that correspond to non c resources deltas. + */ + protected IResourceDelta[] resourceDeltas = null; + + /** + * Counter of resource deltas + */ + protected int resourceDeltasCounter; + + /** + * Empty array of ICElementDelta + */ + protected static ICElementDelta[] fgEmptyDelta= new ICElementDelta[] {}; + + /** + * @see #getAffectedChildren() + */ + protected ICElementDelta[] fAffectedChildren = fgEmptyDelta; + + /** + * Creates the root delta. To create the nested delta + * hierarchies use the following convenience methods. The root + * delta can be created at any level (i.e. project, folder). + * + */ + public CElementDelta(ICElement element) { + super(); + fChangedElement = element; + } + + /** + * Adds the child delta to the collection of affected children. If the + * child is already in the collection, walk down the hierarchy. + */ + protected void addAffectedChild(CElementDelta child) { + switch (fKind) { + case ADDED: + case REMOVED: + // no need to add a child if this parent is added or removed + return; + case CHANGED: + fChangeFlags |= F_CHILDREN; + break; + default: + fKind = CHANGED; + fChangeFlags |= F_CHILDREN; + } + + // if a child delta is added to a translation unit delta or below, + // it's a fine grained delta + try { + if (fChangedElement.getCorrespondingResource() == null) { + fineGrained(); + } + } catch (CModelException e) { + e.printStackTrace(); + } + + if (fAffectedChildren.length == 0) { + fAffectedChildren = new ICElementDelta[] {child}; + return; + } + + // Check if we already have the delta. + ICElementDelta existingChild = null; + int existingChildIndex = -1; + for (int i = 0; i < fAffectedChildren.length; i++) { + // handle case of two jars that can be equals but not in the same project + if (equalsAndSameParent(fAffectedChildren[i].getElement(), child.getElement())) { + existingChild = fAffectedChildren[i]; + existingChildIndex = i; + break; + } + } + + if (existingChild == null) { //new affected child + fAffectedChildren= growAndAddToArray(fAffectedChildren, child); + } else { + switch (existingChild.getKind()) { + case ADDED: + switch (child.getKind()) { + // child was added then added -> it is added + case ADDED: + // child was added then changed -> it is added + case CHANGED: + return; + + // child was added then removed -> noop + case REMOVED: + fAffectedChildren = removeAndShrinkArray(fAffectedChildren, existingChildIndex); + return; + } + break; + case REMOVED: + switch (child.getKind()) { + // child was removed then added -> it is changed + case ADDED: + child.fKind = CHANGED; + fAffectedChildren[existingChildIndex] = child; + return; + + // child was removed then changed -> it is removed + case CHANGED: + // child was removed then removed -> it is removed + case REMOVED: + return; + } + break; + case CHANGED: + switch (child.getKind()) { + // child was changed then added -> it is added + case ADDED: + // child was changed then removed -> it is removed + case REMOVED: + fAffectedChildren[existingChildIndex] = child; + return; + + // child was changed then changed -> it is changed + case CHANGED: + ICElementDelta[] children = child.getAffectedChildren(); + for (int i = 0; i < children.length; i++) { + CElementDelta childsChild = (CElementDelta) children[i]; + ((CElementDelta) existingChild).addAffectedChild(childsChild); + } + // add the non-c resource deltas if needed + // note that the child delta always takes + // precedence over this existing child delta + // as non-c resource deltas are always + // created last (by the DeltaProcessor) + IResourceDelta[] resDeltas = child.getResourceDeltas(); + if (resDeltas != null) { + ((CElementDelta)existingChild).resourceDeltas = resDeltas; + ((CElementDelta)existingChild).resourceDeltasCounter = child.resourceDeltasCounter; + } + return; + } + break; + default: + // unknown -> existing child becomes the child with the existing child's flags + int flags = existingChild.getFlags(); + fAffectedChildren[existingChildIndex] = child; + child.fChangeFlags |= flags; + } + } + } + + /** + * Creates the nested deltas resulting from an add operation. + * Convenience method for creating add deltas. + * The constructor should be used to create the root delta + * and then an add operation should call this method. + */ + public void added(ICElement element) { + CElementDelta addedDelta = new CElementDelta(element); + addedDelta.fKind = ADDED; + insertDeltaTree(element, addedDelta); + // Added also to the Containers + if (element instanceof IArchive) { + CProject cproj = (CProject)element.getCProject(); + ArchiveContainer container = (ArchiveContainer)cproj.getArchiveContainer(); + container.addChild(element); + } else if (element instanceof IBinary) { + if (((IBinary)element).isExecutable() ||((IBinary)element).isSharedLib()) { + CProject cproj = (CProject)element.getCProject(); + BinaryContainer container = (BinaryContainer)cproj.getBinaryContainer(); + container.addChild(element); + } + } + } + + /** + * Adds the child delta to the collection of affected children. If the + * child is already in the collection, walk down the hierarchy. + */ + protected void addResourceDelta(IResourceDelta child) { + switch (fKind) { + case ADDED: + case REMOVED: + // no need to add a child if this parent is added or removed + return; + case CHANGED: + fChangeFlags |= F_CONTENT; + break; + default: + fKind = CHANGED; + fChangeFlags |= F_CONTENT; + } + if (resourceDeltas == null) { + resourceDeltas = new IResourceDelta[5]; + resourceDeltas[resourceDeltasCounter++] = child; + return; + } + if (resourceDeltas.length == resourceDeltasCounter) { + // need a resize + System.arraycopy(resourceDeltas, 0, (resourceDeltas = new IResourceDelta[resourceDeltasCounter * 2]), 0, resourceDeltasCounter); + } + resourceDeltas[resourceDeltasCounter++] = child; + } + + /** + * Creates the nested deltas resulting from a change operation. + * Convenience method for creating change deltas. + * The constructor should be used to create the root delta + * and then a change operation should call this method. + */ + public void changed(ICElement element, int changeFlag) { + CElementDelta changedDelta = new CElementDelta(element); + changedDelta.fKind = CHANGED; + changedDelta.fChangeFlags |= changeFlag; + insertDeltaTree(element, changedDelta); + } + + /** + * Creates the nested deltas for a closed element. + */ + public void closed(ICElement element) { + CElementDelta delta = new CElementDelta(element); + delta.fKind = CHANGED; + delta.fChangeFlags |= F_CLOSED; + insertDeltaTree(element, delta); + } + + /** + * Returns whether the two c elements are equals and have the same parent. + */ + protected boolean equalsAndSameParent(ICElement e1, ICElement e2) { + ICElement parent1; + return e1.equals(e2) && ((parent1 = e1.getParent()) != null) && parent1.equals(e2.getParent()); + } + + /** + * Creates the nested delta deltas based on the affected element + * its delta, and the root of this delta tree. Returns the root + * of the created delta tree. + */ + protected CElementDelta createDeltaTree(ICElement element, CElementDelta delta) { + CElementDelta childDelta = delta; + ArrayList ancestors= getAncestors(element); + if (ancestors == null) { + if (equalsAndSameParent(delta.getElement(), getElement())) { + // handle case of two jars that can be equals but not in the + // same project + // the element being changed is the root element + fKind= delta.fKind; + fChangeFlags = delta.fChangeFlags; + fMovedToHandle = delta.fMovedToHandle; + fMovedFromHandle = delta.fMovedFromHandle; + } else { + // the given delta is not the root or a child - illegal + //Assert.isTrue(false); + } + } else { + for (int i = 0, size = ancestors.size(); i < size; i++) { + ICElement ancestor = (ICElement) ancestors.get(i); + CElementDelta ancestorDelta = new CElementDelta(ancestor); + ancestorDelta.addAffectedChild(childDelta); + childDelta = ancestorDelta; + } + } + return childDelta; + } + + /** + * Returns the CElementDelta for the given element + * in the delta tree, or null, if no delta for the given element is found. + */ + protected CElementDelta find(ICElement e) { + if (equalsAndSameParent(fChangedElement, e)) { // handle case of two jars that can be equals but not in the same project + return this; + } else { + for (int i = 0; i < fAffectedChildren.length; i++) { + CElementDelta delta = ((CElementDelta)fAffectedChildren[i]).find(e); + if (delta != null) { + return delta; + } + } + } + return null; + } + + /** + * Mark this delta as a fine-grained delta. + */ + public void fineGrained() { + fChangeFlags |= F_FINE_GRAINED; + } + + /** + * @see ICElementDelta + */ + public ICElementDelta[] getAddedChildren() { + return getChildrenOfType(ADDED); + } + + /** + * @see ICElementDelta + */ + public ICElementDelta[] getAffectedChildren() { + return fAffectedChildren; + } + + /** + * Returns a collection of all the parents of this element up to (but + * not including) the root of this tree in bottom-up order. If the given + * element is not a descendant of the root of this tree, null + * is returned. + */ + private ArrayList getAncestors(ICElement element) { + ICElement parent = element.getParent(); + if (parent == null) { + return null; + } + ArrayList parents = new ArrayList(); + while (!parent.equals(fChangedElement)) { + parents.add(parent); + parent = parent.getParent(); + if (parent == null) { + return null; + } + } + parents.trimToSize(); + return parents; + } + + /** + * @see ICElementDelta + */ + public ICElementDelta[] getChangedChildren() { + return getChildrenOfType(CHANGED); + } + + /** + * @see ICElementDelta + */ + protected ICElementDelta[] getChildrenOfType(int type) { + int length = fAffectedChildren.length; + if (length == 0) { + return new ICElementDelta[] {}; + } + ArrayList children= new ArrayList(length); + for (int i = 0; i < length; i++) { + if (fAffectedChildren[i].getKind() == type) { + children.add(fAffectedChildren[i]); + } + } + + ICElementDelta[] childrenOfType = new ICElementDelta[children.size()]; + children.toArray(childrenOfType); + return childrenOfType; + } + + /** + * Returns the delta for a given element. Only looks below this + * delta. + */ + protected CElementDelta getDeltaFor(ICElement element) { + if (equalsAndSameParent(getElement(), element)) // handle case of two jars that can be equals but not in the same project + return this; + if (fAffectedChildren.length == 0) + return null; + int childrenCount = fAffectedChildren.length; + for (int i = 0; i < childrenCount; i++) { + CElementDelta delta = (CElementDelta)fAffectedChildren[i]; + if (equalsAndSameParent(delta.getElement(), element)) { // handle case of two jars that can be equals but not in the same project + return delta; + } else { + delta = ((CElementDelta)delta).getDeltaFor(element); + if (delta != null) + return delta; + } + } + return null; + } + + /** + * @see ICElementDelta + */ + public ICElement getElement() { + return fChangedElement; + } + + /** + * @see ICElementDelta + */ + public int getFlags() { + return fChangeFlags; + } + + /** + * @see ICElementDelta + */ + public int getKind() { + return fKind; + } + + /** + * @see ICElementDelta + */ + public ICElement getMovedFromElement() { + return fMovedFromHandle; + } + + /** + * @see ICElementDelta + */ + public ICElement getMovedToElement() { + return fMovedToHandle; + } + + /** + * @see ICElementDelta + */ + public ICElementDelta[] getRemovedChildren() { + return getChildrenOfType(REMOVED); + } + + /** + * Return the collection of resource deltas. Return null if none. + */ + public IResourceDelta[] getResourceDeltas() { + if (resourceDeltas == null) + return null; + if (resourceDeltas.length != resourceDeltasCounter) { + System.arraycopy(resourceDeltas, 0, resourceDeltas = new IResourceDelta[resourceDeltasCounter], 0, resourceDeltasCounter); + } + return resourceDeltas; + } + + /** + * Adds the new element to a new array that contains all of the elements of the old array. + * Returns the new array. + */ + protected ICElementDelta[] growAndAddToArray(ICElementDelta[] array, ICElementDelta addition) { + ICElementDelta[] old = array; + array = new ICElementDelta[old.length + 1]; + System.arraycopy(old, 0, array, 0, old.length); + array[old.length] = addition; + return array; + } + + /** + * Creates the delta tree for the given element and delta, and then + * inserts the tree as an affected child of this node. + */ + protected void insertDeltaTree(ICElement element, CElementDelta delta) { + CElementDelta childDelta= createDeltaTree(element, delta); + if (!equalsAndSameParent(element, getElement())) { + addAffectedChild(childDelta); + } + } + + + /** + * Creates the nested deltas resulting from an move operation. + * Convenience method for creating the "move from" delta. + * The constructor should be used to create the root delta + * and then the move operation should call this method. + */ + public void movedFrom(ICElement movedFromElement, ICElement movedToElement) { + CElementDelta removedDelta = new CElementDelta(movedFromElement); + removedDelta.fKind = REMOVED; + removedDelta.fChangeFlags |= F_MOVED_TO; + removedDelta.fMovedToHandle = movedToElement; + insertDeltaTree(movedFromElement, removedDelta); + } + + /** + * Creates the nested deltas resulting from an move operation. + * Convenience method for creating the "move to" delta. + * The constructor should be used to create the root delta + * and then the move operation should call this method. + */ + public void movedTo(ICElement movedToElement, ICElement movedFromElement) { + CElementDelta addedDelta = new CElementDelta(movedToElement); + addedDelta.fKind = ADDED; + addedDelta.fChangeFlags |= F_MOVED_FROM; + addedDelta.fMovedFromHandle = movedFromElement; + insertDeltaTree(movedToElement, addedDelta); + } + + /** + * Creates the nested deltas for an opened element. + */ + public void opened(ICElement element) { + CElementDelta delta = new CElementDelta(element); + delta.fKind = CHANGED; + delta.fChangeFlags |= F_OPENED; + insertDeltaTree(element, delta); + } + + /** + * Removes the child delta from the collection of affected children. + */ + protected void removeAffectedChild(CElementDelta child) { + int index = -1; + if (fAffectedChildren != null) { + for (int i = 0; i < fAffectedChildren.length; i++) { + if (equalsAndSameParent(fAffectedChildren[i].getElement(), child.getElement())) { // handle case of two jars that can be equals but not in the same project + index = i; + break; + } + } + } + if (index >= 0) { + fAffectedChildren= removeAndShrinkArray(fAffectedChildren, index); + } + } + + /** + * Removes the element from the array. + * Returns the a new array which has shrunk. + */ + protected ICElementDelta[] removeAndShrinkArray(ICElementDelta[] old, int index) { + ICElementDelta[] array = new ICElementDelta[old.length - 1]; + if (index > 0) + System.arraycopy(old, 0, array, 0, index); + int rest = old.length - index - 1; + if (rest > 0) + System.arraycopy(old, index + 1, array, index, rest); + return array; + } + + /** + * Creates the nested deltas resulting from an delete operation. + * Convenience method for creating removed deltas. + * The constructor should be used to create the root delta + * and then the delete operation should call this method. + */ + public void removed(ICElement element) { + CElementDelta removedDelta= new CElementDelta(element); + insertDeltaTree(element, removedDelta); + CElementDelta actualDelta = getDeltaFor(element); + if (actualDelta != null) { + actualDelta.fKind = REMOVED; + actualDelta.fChangeFlags = 0; + actualDelta.fAffectedChildren = fgEmptyDelta; + } + } + + /** + * Creates the nested deltas resulting from a change operation. + * Convenience method for creating change deltas. + * The constructor should be used to create the root delta + * and then a change operation should call this method. + */ + public void sourceAttached(ICElement element) { + CElementDelta attachedDelta = new CElementDelta(element); + attachedDelta.fKind = CHANGED; + attachedDelta.fChangeFlags |= F_SOURCEATTACHED; + insertDeltaTree(element, attachedDelta); + } + + /** + * Creates the nested deltas resulting from a change operation. + * Convenience method for creating change deltas. + * The constructor should be used to create the root delta + * and then a change operation should call this method. + */ + public void sourceDetached(ICElement element) { + CElementDelta detachedDelta = new CElementDelta(element); + detachedDelta.fKind = CHANGED; + detachedDelta.fChangeFlags |= F_SOURCEDETACHED; + insertDeltaTree(element, detachedDelta); + } + + /** + * Returns a string representation of this delta's + * structure suitable for debug purposes. + * + * @see toString + */ + public String toDebugString(int depth) { + StringBuffer buffer = new StringBuffer(); + for (int i= 0; i < depth; i++) { + buffer.append('\t'); + } + buffer.append(((CElement)getElement()).toDebugString()); + buffer.append(" ["); //$NON-NLS-1$ + switch (getKind()) { + case ICElementDelta.ADDED : + buffer.append('+'); + break; + case ICElementDelta.REMOVED : + buffer.append('-'); + break; + case ICElementDelta.CHANGED : + buffer.append('*'); + break; + default : + buffer.append('?'); + break; + } + buffer.append("]: {"); //$NON-NLS-1$ + int changeFlags = getFlags(); + boolean prev = false; + if ((changeFlags & ICElementDelta.F_CHILDREN) != 0) { + if (prev) + buffer.append(" | "); //$NON-NLS-1$ + buffer.append("CHILDREN"); //$NON-NLS-1$ + prev = true; + } + if ((changeFlags & ICElementDelta.F_CONTENT) != 0) { + if (prev) + buffer.append(" | "); //$NON-NLS-1$ + buffer.append("CONTENT"); //$NON-NLS-1$ + prev = true; + } + if ((changeFlags & ICElementDelta.F_MOVED_FROM) != 0) { + if (prev) + buffer.append(" | "); //$NON-NLS-1$ + //buffer.append("MOVED_FROM(" + ((CElement)getMovedFromElement()).toStringWithAncestors() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + prev = true; + } + if ((changeFlags & ICElementDelta.F_MOVED_TO) != 0) { + if (prev) + buffer.append(" | "); //$NON-NLS-1$ + //buffer.append("MOVED_TO(" + ((CElement)getMovedToElement()).toStringWithAncestors() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ + prev = true; + } + if ((changeFlags & ICElementDelta.F_MODIFIERS) != 0) { + if (prev) + buffer.append(" | "); //$NON-NLS-1$ + buffer.append("MODIFIERS CHANGED"); //$NON-NLS-1$ + prev = true; + } + //if ((changeFlags & ICElementDelta.F_SUPER_TYPES) != 0) { + // if (prev) + // buffer.append(" | "); //$NON-NLS-1$ + // buffer.append("SUPER TYPES CHANGED"); //$NON-NLS-1$ + // prev = true; + //} + if ((changeFlags & ICElementDelta.F_FINE_GRAINED) != 0) { + if (prev) + buffer.append(" | "); //$NON-NLS-1$ + buffer.append("FINE GRAINED"); //$NON-NLS-1$ + prev = true; + } + buffer.append("}"); //$NON-NLS-1$ + ICElementDelta[] children = getAffectedChildren(); + if (children != null) { + for (int i = 0; i < children.length; ++i) { + buffer.append("\n"); //$NON-NLS-1$ + buffer.append(((CElementDelta) children[i]).toDebugString(depth + 1)); + } + } + + for (int i = 0; i < resourceDeltasCounter; i++) { + buffer.append("\n");//$NON-NLS-1$ + for (int j = 0; j < depth+1; j++) { + buffer.append('\t'); + } + IResourceDelta resourceDelta = resourceDeltas[i]; + buffer.append(resourceDelta.toString()); + buffer.append("["); //$NON-NLS-1$ + switch (resourceDelta.getKind()) { + case IResourceDelta.ADDED : + buffer.append('+'); + break; + case IResourceDelta.REMOVED : + buffer.append('-'); + break; + case IResourceDelta.CHANGED : + buffer.append('*'); + break; + default : + buffer.append('?'); + break; + } + buffer.append("]"); //$NON-NLS-1$ + } + return buffer.toString(); + } + + /** + * Returns a string representation of this delta's + * structure suitable for debug purposes. + */ + public String toString() { + return toDebugString(0); + } + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementInfo.java new file mode 100644 index 00000000000..333c15e2ac0 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CElementInfo.java @@ -0,0 +1,184 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.File; + +import org.eclipse.core.resources.IResource; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.CModelException; + +/** + * Holds cached structure and properties for a C element. + * Subclassed to carry properties for specific kinds of elements. + */ +class CElementInfo { + + protected CElement element; + + /** + * Collection of handles of immediate children of this + * object. This is an empty array if this element has + * no children. + */ + protected ICElement[] fChildren; + + /** + * Shared empty collection used for efficiency. + */ + protected static ICElement[] fgEmptyChildren = new ICElement[]{}; + /** + * Is the structure of this element known + * @see ICElement.isStructureKnown() + */ + protected boolean fIsStructureKnown = false; + + protected long modificationStamp = 0; + + protected CElementInfo(CElement element) { + this.element = element; + fChildren = fgEmptyChildren; + } + + protected CElement getElement() { + return element; + } + + protected void addChild(ICElement child) { + if (fChildren == fgEmptyChildren) { + setChildren(new ICElement[] {child}); + } else { + if (!includesChild(child)) { + setChildren(growAndAddToArray(fChildren, child)); + } + } + } + + protected ICElement[] getChildren() { + return fChildren; + } + + /** + * Adds the new element to a new array that contains all of the elements of the old array. + * Returns the new array. + */ + protected ICElement[] growAndAddToArray(ICElement[] array, ICElement addition) { + ICElement[] old = array; + array = new ICElement[old.length + 1]; + System.arraycopy(old, 0, array, 0, old.length); + array[old.length] = addition; + return array; + } + + /** + * Returns true if this child is in my children collection + */ + protected boolean includesChild(ICElement child) { + + for (int i= 0; i < fChildren.length; i++) { + if (fChildren[i].equals(child)) { + return true; + } + } + return false; + } + + /** + * @see ICElement.isStructureKnown() + */ + protected boolean isStructureKnown() { + return fIsStructureKnown; + } + + /** + * Returns an array with all the same elements as the specified array except for + * the element to remove. Assumes that the deletion is contained in the array. + */ + protected ICElement[] removeAndShrinkArray(ICElement[] array, ICElement deletion) { + ICElement[] old = array; + array = new ICElement[old.length - 1]; + int j = 0; + for (int i = 0; i < old.length; i++) { + if (!old[i].equals(deletion)) { + array[j] = old[i]; + } else { + System.arraycopy(old, i + 1, array, j, old.length - (i + 1)); + return array; + } + j++; + } + return array; + } + + protected void removeChild(ICElement child) { + if (includesChild(child)) { + setChildren(removeAndShrinkArray(fChildren, child)); + } + } + + protected void removeChildren () { + fChildren = fgEmptyChildren; + } + + protected void setChildren(ICElement[] children) { + fChildren = children; + } + + protected boolean hasChildren() { + return fChildren.length > 0; + } + + protected void setChanged() { + modificationStamp = 0; + } + + protected boolean hasChanged () { + IResource r = null; + boolean b = false; + try { + r = getElement().getUnderlyingResource(); + } catch (CModelException e) { + e.printStackTrace(); + } + if (r != null && r.exists()) { + long modif = 0; + switch(r.getType()) { + // Adding/Removing does not count as changing, in Eclipse + // Ask the underlying file system + case IResource.FOLDER: + case IResource.PROJECT: + case IResource.ROOT: + File file = r.getLocation().toFile(); + modif = file.lastModified(); + break; + + case IResource.FILE: + modif = r.getModificationStamp(); + break; + } + b = (modif != modificationStamp); + modificationStamp = modif; + } + return b; + } + + /** + * Sets whether the structure of this element known + * @see ICElement.isStructureKnown() + */ + protected void setIsStructureKnown(boolean newIsStructureKnown) { + fIsStructureKnown = newIsStructureKnown; + } + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + throw new Error(); + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFile.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFile.java new file mode 100644 index 00000000000..5ac68f0a25d --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFile.java @@ -0,0 +1,76 @@ +package org.eclipse.cdt.internal.core.model; +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +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.CoreException; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFile; + +public class CFile extends CResource implements ICFile { + + IPath location; + + public CFile(ICElement parent, IFile file) { + this(parent, file, file.getLocation(), file.getName()); + } + + public CFile(ICElement parent, IFile file, String name) { + this(parent, file, file.getLocation(), name); + } + + public CFile(ICElement parent, IPath location) { + this(parent, ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(location), + location, location.lastSegment()); + } + + public CFile(ICElement parent, IResource res, IPath location, String name) { + super(parent, res, name, CElement.C_FILE); + this.location = location; + } + + + public IPath getLocation () { + return location; + } + + public void setLocation(IPath location) { + this.location = location; + } + + public IFile getFile () { + try { + return (IFile)getUnderlyingResource(); + } catch (CModelException e) { + e.printStackTrace(); + } + return null; + } + + public boolean isBinary() { + return getCFileInfo().isBinary(); + } + + public boolean isArchive() { + return getCFileInfo().isArchive(); + } + + public boolean isTranslationUnit() { + return getCFileInfo().isTranslationUnit(); + } + + protected CFileInfo getCFileInfo() { + return (CFileInfo)getElementInfo(); + } + + protected CElementInfo createElementInfo () { + return new CFileInfo(this); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFileInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFileInfo.java new file mode 100644 index 00000000000..b31f3745031 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFileInfo.java @@ -0,0 +1,32 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +public class CFileInfo extends CResourceInfo { + + /** + * Constructs a new C Model Info + */ + protected CFileInfo(CElement element) { + super(element); + } + + protected boolean hasChildren() { + return false; + } + + public boolean isBinary() { + return false; + } + + public boolean isArchive() { + return false; + } + + public boolean isTranslationUnit() { + return (this instanceof TranslationUnitInfo); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolder.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolder.java new file mode 100644 index 00000000000..a7547a12ef9 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolder.java @@ -0,0 +1,32 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IFolder; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICFolder; +import org.eclipse.cdt.core.model.CModelException; + +public class CFolder extends CResource implements ICFolder { + + public CFolder (ICElement parent, IFolder folder) { + super (parent, folder, ICElement.C_FOLDER); + } + + public IFolder getFolder () { + try { + return (IFolder)getUnderlyingResource(); + } catch (CModelException e) { + e.printStackTrace(); + } + return null; + } + + protected CElementInfo createElementInfo () { + return new CFolderInfo(this); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolderInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolderInfo.java new file mode 100644 index 00000000000..c95dbc0ed66 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CFolderInfo.java @@ -0,0 +1,18 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + */ +public class CFolderInfo extends CResourceInfo { + + /** + * Constructs a new C Model Info + */ + protected CFolderInfo(CElement element) { + super(element); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java new file mode 100644 index 00000000000..4910f547dc8 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java @@ -0,0 +1,701 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.IOException; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Arrays; +import java.util.Iterator; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IArchive; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.IElementChangedListener; +import org.eclipse.cdt.core.model.ElementChangedEvent; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.CModelException; + +import org.eclipse.cdt.core.model.CoreModel; + +import org.eclipse.cdt.utils.elf.Elf; +import org.eclipse.cdt.utils.elf.AR; + +public class CModelManager implements IResourceChangeListener { + + // FIXME: Get it from the plugin class. + private static String C_NATURE_ID = CoreModel.getCNatureId(); + private static String CC_NATURE_ID = CoreModel.getCCNatureId(); + + private HashMap fParsedResources = new HashMap(); + + /** + * Used to convert IResourceDeltas into IJavaElementDeltas. + */ + protected DeltaProcessor fDeltaProcessor= new DeltaProcessor(); + + /** + * Queue of deltas created explicily by the C Model that + * have yet to be fired. + */ + private ArrayList fCModelDeltas= new ArrayList(); + + /** + * Turns delta firing on/off. By default it is on. + */ + protected boolean fFire= true; + + /** + * Collection of listeners for C element deltas + */ + protected ArrayList fElementChangedListeners= new ArrayList(); + + public static final String [] cExtensions = {"c", "cxx", "cc", "C", "cpp", "h", "hh"}; + + static CModelManager factory = null; + + private CModelManager() { + } + + public static CModelManager getDefault() { + if (factory == null) { + factory = new CModelManager (); + + // Register to the workspace; + ResourcesPlugin.getWorkspace().addResourceChangeListener(factory, + IResourceChangeEvent.PRE_AUTO_BUILD + | IResourceChangeEvent.POST_CHANGE + | IResourceChangeEvent.PRE_DELETE + | IResourceChangeEvent.PRE_CLOSE); + } + return factory; + } + + /** + * Returns the CRoot for the given workspace, creating + * it if it does not yet exist. + */ + public ICElement getCRoot(IWorkspaceRoot root) { + return create(root); + } + + public ICElement getCRoot () { + return create(ResourcesPlugin.getWorkspace().getRoot()); + } + + public ICElement create (IPath path) { + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + // Assume it is fullpath relative to workspace + IResource res = root.findMember(path); + if (res == null) { + IPath rootPath = root.getLocation(); + if (path.equals(rootPath)) + return getCRoot(root); + res = root.getContainerForLocation(path); + if (res == null) + res = root.getFileForLocation(path); + } + return create (res); + } + + public ICElement create (IResource resource) { + if (resource == null) { + return null; + } + int type = resource.getType(); + switch (type) { + case IResource.PROJECT : + return create((IProject)resource); + case IResource.FILE : + return create((IFile)resource); + case IResource.FOLDER : + return create((IFolder)resource); + case IResource.ROOT : + return create((IWorkspaceRoot)resource); + default : + return null; + } + } + + public ICElement create(ICElement parent, IResource resource) { + int type = resource.getType(); + switch (type) { + case IResource.PROJECT : + return create(parent, (IProject)resource); + case IResource.FILE : + return create(parent, (IFile)resource); + case IResource.FOLDER : + return create(parent, (IFolder)resource); + case IResource.ROOT : + return create(parent, (IWorkspaceRoot)resource); + default : + return null; + } + } + + public ICElement create(IFile file) { + IResource parent = file.getParent(); + ICElement celement = null; + if (parent instanceof IFolder) { + celement = create ((IFolder)parent); + } else if (parent instanceof IProject) { + celement = create ((IProject)parent); + } + if (celement != null) + return create (celement, file); + return celement; + } + + public synchronized ICElement create(ICElement parent, IFile file) { + ICElement celement = (ICElement)fParsedResources.get(file); + if (celement == null) { + if (file.exists()) { + if (isArchive(file)) { + celement = new Archive(parent, file); + } else if (isBinary(file)) { + celement = new Binary(parent, file); + } else if (isTranslationUnit(file)) { + celement = new TranslationUnit(parent, file); + } else { + celement = new CFile(parent, file); + } + fParsedResources.put(file, celement); + } + } + // Added also to the Containers + if (celement != null) { + if (celement instanceof IArchive) { + CProject cproj = (CProject)celement.getCProject(); + ArchiveContainer container = (ArchiveContainer)cproj.getArchiveContainer(); + container.addChild(celement); + } else if (celement instanceof IBinary) { + IBinary bin = (IBinary)celement; + if (bin.isExecutable() || bin.isSharedLib()) { + CProject cproj = (CProject)celement.getCProject(); + BinaryContainer container = (BinaryContainer)cproj.getBinaryContainer(); + container.addChild(bin); + } + } + } + return celement; + } + + public ICElement create(IFolder folder) { + IResource parent = folder.getParent(); + ICElement celement = null; + if (parent instanceof IFolder) { + celement = create ((IFolder)parent); + } else if (parent instanceof IProject) { + celement = create ((IProject)parent); + } + if (celement != null) + return create (celement, folder); + return celement; + } + + public synchronized ICElement create(ICElement parent, IFolder folder) { + ICElement celement = (ICElement)fParsedResources.get(folder); + if (celement == null) { + celement = new CFolder(parent, folder); + fParsedResources.put(folder, celement); + } + return celement; + } + + public ICElement create(IProject project) { + IResource parent = project.getParent(); + ICElement celement = null; + if (parent instanceof IWorkspaceRoot) { + celement = create ((IWorkspaceRoot)parent); + } + return create(celement, project); + } + + public synchronized ICElement create(ICElement parent, IProject project) { + ICElement celement = (ICElement)fParsedResources.get(project); + if (celement == null) { + if (hasCNature(project)) { + celement = new CProject(parent, project); + fParsedResources.put(project, celement); + } + } + return celement; + } + + public ICElement create(IWorkspaceRoot root) { + ICElement celement = (ICElement)fParsedResources.get(root); + if (celement == null) { + celement = new CRoot(root); + fParsedResources.put(root, celement); + } + return celement; + } + + public static void addCNature(IProject project, IProgressMonitor monitor) throws CModelException { + addNature(project, C_NATURE_ID, monitor); + } + + public static void addCCNature(IProject project, IProgressMonitor monitor) throws CModelException { + addNature(project, CC_NATURE_ID, monitor); + } + + public static void removeCNature(IProject project, IProgressMonitor monitor) throws CModelException { + removeNature(project, C_NATURE_ID, monitor); + } + + public static void removeCCNature(IProject project, IProgressMonitor monitor) throws CModelException { + removeNature(project, CC_NATURE_ID, monitor); + } + + /** + * Utility method for adding a nature to a project. + * + * @param proj the project to add the nature + * @param natureId the id of the nature to assign to the project + * @param monitor a progress monitor to indicate the duration of the operation, or + * null if progress reporting is not required. + * + */ + public static void addNature(IProject project, String natureId, IProgressMonitor monitor) throws CModelException { + try { + IProjectDescription description = project.getDescription(); + String[] prevNatures= description.getNatureIds(); + for (int i= 0; i < prevNatures.length; i++) { + if (natureId.equals(prevNatures[i])) + return; + } + String[] newNatures= new String[prevNatures.length + 1]; + System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length); + newNatures[prevNatures.length]= natureId; + description.setNatureIds(newNatures); + project.setDescription(description, monitor); + } catch (CoreException e) { + throw new CModelException(e); + } + } + + /** + * Utility method for removing a project nature from a project. + * + * @param proj the project to remove the nature from + * @param natureId the nature id to remove + * @param monitor a progress monitor to indicate the duration of the operation, or + * null if progress reporting is not required. + */ + public static void removeNature(IProject project, String natureId, IProgressMonitor monitor) throws CModelException { + try { + IProjectDescription description = project.getDescription(); + String[] prevNatures= description.getNatureIds(); + List newNatures = new ArrayList(Arrays.asList(prevNatures)); + newNatures.remove(natureId); + description.setNatureIds((String[])newNatures.toArray(new String[newNatures.size()])); + project.setDescription(description, monitor); + } catch (CoreException e) { + throw new CModelException(e); + } + } + + private void removeChildrenContainer(Parent container, IResource resource) { + ICElement[] children = container.getChildren(); + for (int i = 0; i < children.length; i++) { + try { + IResource r = children[i].getUnderlyingResource(); + if (r.equals(resource)) { +//System.out.println("RELEASE Archive/binary " + children[i].getElementName()); + container.removeChild(children[i]); + break; + } + } catch (CModelException e) { + } + } + } + + + public void releaseCElement(IResource resource) { + ICElement celement = getCElement(resource); + if (celement == null) { + if (resource.exists()) { + celement = create(resource); + } else { + // Make sure they are not in the Containers. + CProject cproj = (CProject)create(resource.getProject()); + if (cproj != null) { + Parent container = (Parent)cproj.getArchiveContainer(); + removeChildrenContainer(container, resource); + container = (Parent)cproj.getBinaryContainer(); + removeChildrenContainer(container, resource); + } + } + } + releaseCElement(celement); + } + + public void releaseCElement(ICElement celement) { + + // Guard. + if (celement == null) + return; + +//System.out.println("RELEASE " + celement.getElementName()); + + // Remove from the containers. + if (celement.getElementType() == ICElement.C_FILE) { + CFile cfile = (CFile)celement; + if (cfile.isArchive()) { +//System.out.println("RELEASE Archive " + cfile.getElementName()); + CProject cproj = (CProject)cfile.getCProject(); + ArchiveContainer container = (ArchiveContainer)cproj.getArchiveContainer(); + container.removeChild(cfile); + } else if (cfile.isBinary()) { + if (! ((IBinary)celement).isObject()) { +//System.out.println("RELEASE Binary " + cfile.getElementName()); + CProject cproj = (CProject)cfile.getCProject(); + BinaryContainer container = (BinaryContainer)cproj.getBinaryContainer(); + container.removeChild(cfile); + } + } + } + + Parent parent = (Parent)celement.getParent(); + if (parent != null) { + parent.removeChild(celement); + } + fParsedResources.remove(celement); + } + + public ICElement getCElement(IResource res) { + return (ICElement)fParsedResources.get(res); + } + + public ICElement getCElement(IPath path) { + Iterator iterator = fParsedResources.keySet().iterator(); + while (iterator.hasNext()) { + IResource res = (IResource)iterator.next(); + if (res.getFullPath().equals(path)) { + return (ICElement)fParsedResources.get(res); + } + } + return null; + } + + public static boolean isSharedLib(IFile file) { + try { + Elf.Attribute attribute = Elf.getAttributes(file.getLocation().toOSString()); + if (attribute.getType() == Elf.Attribute.ELF_TYPE_SHLIB) { + return true; + } + } catch (IOException e) { + //e.printStackTrace(); + } + return false; + } + + public static boolean isObject(IFile file) { + try { + Elf.Attribute attribute = Elf.getAttributes(file.getLocation().toOSString()); + if (attribute.getType() == Elf.Attribute.ELF_TYPE_OBJ) { + return true; + } + } catch (IOException e) { + //e.printStackTrace(); + } + return false; + } + + public static boolean isExecutable(IFile file) { + try { + Elf.Attribute attribute = Elf.getAttributes(file.getLocation().toOSString()); + if (attribute.getType() == Elf.Attribute.ELF_TYPE_EXE) { + return true; + } + } catch (IOException e) { + //e.printStackTrace(); + } + return false; + } + + public static boolean isBinary(IFile file) { + try { + Elf.Attribute attribute = Elf.getAttributes(file.getLocation().toOSString()); + if (attribute.getType() == Elf.Attribute.ELF_TYPE_EXE + || attribute.getType() == Elf.Attribute.ELF_TYPE_OBJ + || attribute.getType() == Elf.Attribute.ELF_TYPE_SHLIB) { + return true; + } + } catch (IOException e) { + //e.printStackTrace(); + } + return false; + } + + public static boolean isArchive(IFile file) { + AR ar = null; + try { + ar = new AR(file.getLocation().toOSString()); + } catch (IOException e) { + //e.printStackTrace(); + } + if (ar != null) { + ar.dispose(); + return true; + } + return false; + } + + public static boolean isTranslationUnit(IFile file) { + return isValidTranslationUnitName(file.getName()); + } + + public static boolean isValidTranslationUnitName(String name){ + if (name == null) { + return false; + } + int index = name.lastIndexOf('.'); + if (index == -1) { + return false; + } + String ext = name.substring(index + 1); + for (int i = 0; i < cExtensions.length; i++) { + if (ext.equals(cExtensions[i])) + return true; + } + return false; + } + + /* Only project with C nature and Open. */ + public static boolean hasCNature (IProject p) { + boolean ok = false; + try { + ok = (p.isOpen() && p.hasNature(C_NATURE_ID)); + } catch (CoreException e) { + //throws exception if the project is not open. + //System.out.println (e); + //e.printStackTrace(); + } + return ok; + } + + /* Only project with C++ nature and Open. */ + public static boolean hasCCNature (IProject p) { + boolean ok = false; + try { + ok = (p.isOpen() && p.hasNature(CC_NATURE_ID)); + } catch (CoreException e) { + //throws exception if the project is not open. + //System.out.println (e); + //e.printStackTrace(); + } + return ok; + } + + /** + * addElementChangedListener method comment. + */ + public synchronized void addElementChangedListener(IElementChangedListener listener) { + if (fElementChangedListeners.indexOf(listener) < 0) { + fElementChangedListeners.add(listener); + } + } + + /** + * removeElementChangedListener method comment. + */ + public synchronized void removeElementChangedListener(IElementChangedListener listener) { + int i = fElementChangedListeners.indexOf(listener); + if (i != -1) { + fElementChangedListeners.remove(i); + } + } + + /** + * Registers the given delta with this manager. This API is to be + * used to registerd deltas that are created explicitly by the C + * Model. Deltas created as translations of IResourceDeltas + * are to be registered with #registerResourceDelta. + */ + public synchronized void registerCModelDelta(ICElementDelta delta) { + fCModelDeltas.add(delta); + } + + /** + * Notifies this C Model Manager that some resource changes have happened + * on the platform, and that the C Model should update any required + * internal structures such that its elements remain consistent. + * Translates IResourceDeltas into ICElementDeltas. + * + * @see IResourceDelta + * @see IResource + */ + public void resourceChanged(IResourceChangeEvent event) { + + if (event.getSource() instanceof IWorkspace) { + IResource resource = event.getResource(); + IResourceDelta delta = event.getDelta(); + switch(event.getType()){ + case IResourceChangeEvent.PRE_DELETE : + if(resource.getType() == IResource.PROJECT + && hasCNature((IProject)resource)) { + releaseCElement(resource); + } + break; + + case IResourceChangeEvent.PRE_AUTO_BUILD : + // will close project if affected by the property file change + break; + + case IResourceChangeEvent.POST_CHANGE : + if (delta != null) { + try { + ICElementDelta[] translatedDeltas = fDeltaProcessor.processResourceDelta(delta); + if (translatedDeltas.length > 0) { + for (int i= 0; i < translatedDeltas.length; i++) { + registerCModelDelta(translatedDeltas[i]); + } + } + fire(); + } catch (Exception e) { + e.printStackTrace(); + } + } + break; + } + } + } + + /** + * Note that the project is about to be deleted. + * + * fix for 1FW67PA + */ + public void deleting(IResource resource) { + deleting(getCElement(resource)); + } + + public void deleting(ICElement celement) { + releaseCElement(celement); + } + + /** + * Fire C Model deltas, flushing them after the fact. + * If the firing mode has been turned off, this has no effect. + */ + public synchronized void fire() { + if (fFire) { + mergeDeltas(); + try { + Iterator iterator = fCModelDeltas.iterator(); + while (iterator.hasNext()) { + ICElementDelta delta= (ICElementDelta) iterator.next(); + + // Refresh internal scopes + + ElementChangedEvent event= new ElementChangedEvent(delta); + // Clone the listeners since they could remove themselves when told about the event + // (eg. a type hierarchy becomes invalid (and thus it removes itself) when the type is removed + ArrayList listeners= (ArrayList) fElementChangedListeners.clone(); + for (int i= 0; i < listeners.size(); i++) { + IElementChangedListener listener= (IElementChangedListener) listeners.get(i); + listener.elementChanged(event); + } + } + } finally { + // empty the queue + this.flush(); + } + } + } + + /** + * Flushes all deltas without firing them. + */ + protected synchronized void flush() { + fCModelDeltas= new ArrayList(); + } + + /** + * Merged all awaiting deltas. + */ + private void mergeDeltas() { + if (fCModelDeltas.size() <= 1) + return; + + Iterator deltas = fCModelDeltas.iterator(); + ICElement cRoot = getCRoot(); + CElementDelta rootDelta = new CElementDelta(cRoot); + boolean insertedTree = false; + while (deltas.hasNext()) { + CElementDelta delta = (CElementDelta)deltas.next(); + ICElement element = delta.getElement(); + if (cRoot.equals(element)) { + ICElementDelta[] children = delta.getAffectedChildren(); + for (int j = 0; j < children.length; j++) { + CElementDelta projectDelta = (CElementDelta) children[j]; + rootDelta.insertDeltaTree(projectDelta.getElement(), projectDelta); + insertedTree = true; + } + } else { + rootDelta.insertDeltaTree(element, delta); + insertedTree = true; + } + } + if (insertedTree){ + fCModelDeltas = new ArrayList(1); + fCModelDeltas.add(rootDelta); + } else { + fCModelDeltas = new ArrayList(0); + } + } + + /** + * Runs a C Model Operation + */ + public void runOperation(CModelOperation operation, IProgressMonitor monitor) throws CModelException { + boolean hadAwaitingDeltas = !fCModelDeltas.isEmpty(); + try { + if (operation.isReadOnly()) { + operation.run(monitor); + } else { + // use IWorkspace.run(...) to ensure that a build will be done in autobuild mode + getCRoot().getUnderlyingResource().getWorkspace().run(operation, monitor); + } + } catch (CoreException ce) { + if (ce instanceof CModelException) { + throw (CModelException)ce; + } else { + if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) { + Throwable e= ce.getStatus().getException(); + if (e instanceof CModelException) { + throw (CModelException) e; + } + } + throw new CModelException(ce); + } + } finally { +// fire only if there were no awaiting deltas (if there were, they would come from a resource modifying operation) +// and the operation has not modified any resource + if (!hadAwaitingDeltas && !operation.hasModifiedResource()) { + fire(); + } // else deltas are fired while processing the resource delta + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelOperation.java new file mode 100644 index 00000000000..95117b3699c --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelOperation.java @@ -0,0 +1,553 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +import java.io.InputStream; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.SubProgressMonitor; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ICRoot; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.ICModelStatusConstants; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.CModelException; + +/** + * Defines behavior common to all C Model operations + */ +public abstract class CModelOperation implements IWorkspaceRunnable, IProgressMonitor { + /** + * The elements this operation operates on, + * or null if this operation + * does not operate on specific elements. + */ + protected ICElement[] fElementsToProcess; + + /** + * The parent elements this operation operates with + * or null if this operation + * does not operate with specific parent elements. + */ + protected ICElement[] fParentElements; + + /** + * An empty collection of ICElements - the common + * empty result if no elements are created, or if this + * operation is not actually executed. + */ + protected static ICElement[] fgEmptyResult= new ICElement[] {}; + + /** + * Collection of ICElementDeltas created by this operation. + * This collection starts out null and becomes an + * array of ICElementDeltas if the operation creates any + * deltas. This collection is registered with the C Model notification + * manager if the operation completes successfully. + */ + protected ICElementDelta[] fDeltas= null; + + /** + * The elements created by this operation - empty + * until the operation actually creates elements. + */ + protected ICElement[] fResultElements= fgEmptyResult; + + /** + * The progress monitor passed into this operation + */ + protected IProgressMonitor fMonitor= null; + + /** + * A flag indicating whether this operation is nested. + */ + protected boolean fNested = false; + + /** + * Conflict resolution policy - by default do not force (fail on a conflict). + */ + protected boolean fForce= false; + + /* + * Whether the operation has modified resources, and thus whether resource + * delta notifcation will happen. + */ + protected boolean hasModifiedResource = false; + + /** + * A common constructor for all C Model operations. + */ + protected CModelOperation(ICElement[] elements) { + fElementsToProcess = elements; + } + + /** + * Common constructor for all C Model operations. + */ + protected CModelOperation(ICElement[] elementsToProcess, ICElement[] parentElements) { + fElementsToProcess = elementsToProcess; + fParentElements= parentElements; + } + + /** + * A common constructor for all C Model operations. + */ + protected CModelOperation(ICElement[] elementsToProcess, ICElement[] parentElements, boolean force) { + fElementsToProcess = elementsToProcess; + fParentElements= parentElements; + fForce= force; + } + + /** + * A common constructor for all C Model operations. + */ + protected CModelOperation(ICElement[] elements, boolean force) { + fElementsToProcess = elements; + fForce= force; + } + + /** + * Common constructor for all C Model operations. + */ + protected CModelOperation(ICElement element) { + fElementsToProcess = new ICElement[]{element}; + } + + /** + * A common constructor for all C Model operations. + */ + protected CModelOperation(ICElement element, boolean force) { + fElementsToProcess = new ICElement[]{element}; + fForce= force; + } + + /** + * Adds the given delta to the collection of deltas + * that this operation has created. These deltas are + * automatically registered with the C Model Manager + * when the operation completes. + */ + protected void addDelta(ICElementDelta delta) { + if (fDeltas == null) { + fDeltas= new ICElementDelta[] {delta}; + } else { + ICElementDelta[] copy= new ICElementDelta[fDeltas.length + 1]; + System.arraycopy(fDeltas, 0, copy, 0, fDeltas.length); + copy[fDeltas.length]= delta; + fDeltas= copy; + } + } + + /** + * @see IProgressMonitor + */ + public void beginTask(String name, int totalWork) { + if (fMonitor != null) { + fMonitor.beginTask(name, totalWork); + } + } + + /** + * Checks with the progress monitor to see whether this operation + * should be canceled. An operation should regularly call this method + * during its operation so that the user can cancel it. + * + * @exception OperationCanceledException if cancelling the operation has been requested + * @see IProgressMonitor#isCanceled + */ + protected void checkCanceled() { + if (isCanceled()) { + throw new OperationCanceledException("operation.cancelled"); //$NON-NLS-1$ + } + } + + /** + * Common code used to verify the elements this operation is processing. + * @see CModelOperation#verify() + */ + protected ICModelStatus commonVerify() { + if (fElementsToProcess == null || fElementsToProcess.length == 0) { + return new CModelStatus(ICModelStatusConstants.NO_ELEMENTS_TO_PROCESS); + } + for (int i = 0; i < fElementsToProcess.length; i++) { + if (fElementsToProcess[i] == null) { + return new CModelStatus(ICModelStatusConstants.NO_ELEMENTS_TO_PROCESS); + } + } + return CModelStatus.VERIFIED_OK; + } + + /** + * Convenience method to copy resources + */ + protected void copyResources(IResource[] resources, IPath destinationPath) throws CModelException { + IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length); + IWorkspace workspace = resources[0].getWorkspace(); + try { + workspace.copy(resources, destinationPath, false, subProgressMonitor); + this.hasModifiedResource = true; + } catch (CoreException e) { + throw new CModelException(e); + } + } + + /** + * Convenience method to create a file + */ + protected void createFile(IContainer folder, String name, InputStream contents, boolean force) throws CModelException { + IFile file= folder.getFile(new Path(name)); + try { + file.create(contents, force, getSubProgressMonitor(1)); + this.hasModifiedResource = true; + } catch (CoreException e) { + throw new CModelException(e); + } + } + + /** + * Convenience method to create a folder + */ + protected void createFolder(IContainer parentFolder, String name, boolean force) throws CModelException { + IFolder folder= parentFolder.getFolder(new Path(name)); + try { + // we should use true to create the file locally. Only VCM should use tru/false + folder.create(force, true, getSubProgressMonitor(1)); + this.hasModifiedResource = true; + } catch (CoreException e) { + throw new CModelException(e); + } + } + + /** + * Convenience method to delete a resource + */ + protected void deleteResource(IResource resource, boolean force) throws CModelException { + try { + resource.delete(force, getSubProgressMonitor(1)); + this.hasModifiedResource = true; + } catch (CoreException e) { + throw new CModelException(e); + } + } + + /** + * Convenience method to delete resources + */ + protected void deleteResources(IResource[] resources, boolean force) throws CModelException { + if (resources == null || resources.length == 0) return; + IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length); + IWorkspace workspace = resources[0].getWorkspace(); + try { + workspace.delete(resources, force, subProgressMonitor); + this.hasModifiedResource = true; + } catch (CoreException e) { + throw new CModelException(e); + } + } + + /** + * @see IProgressMonitor + */ + public void done() { + if (fMonitor != null) { + fMonitor.done(); + } + } + + /** + * Verifies the operation can proceed and executes the operation. + * Subclasses should override #verify and + * executeOperation to implement the specific operation behavior. + * + * @exception CModelException The operation has failed. + */ + protected void execute() throws CModelException { + ICModelStatus status= verify(); + if (status.isOK()) { + executeOperation(); + } else { + throw new CModelException(status); + } + } + + /** + * Convenience method to run an operation within this operation + */ + public void executeNestedOperation(CModelOperation operation, int subWorkAmount) throws CModelException { + IProgressMonitor subProgressMonitor = getSubProgressMonitor(subWorkAmount); + // fix for 1FW7IKC, part (1) + try { + operation.setNested(true); + operation.run(subProgressMonitor); + if (operation.hasModifiedResource()) { + this.hasModifiedResource = true; + } + //accumulate the nested operation deltas + if (operation.fDeltas != null) { + for (int i = 0; i < operation.fDeltas.length; i++) { + addDelta(operation.fDeltas[i]); + } + } + } catch (CoreException ce) { + if (ce instanceof CModelException) { + throw (CModelException)ce; + } else { + // translate the core exception to a c model exception + if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) { + Throwable e = ce.getStatus().getException(); + if (e instanceof CModelException) { + throw (CModelException) e; + } + } + throw new CModelException(ce); + } + } + } + + /** + * Performs the operation specific behavior. Subclasses must override. + */ + protected abstract void executeOperation() throws CModelException; + + /** + * Returns the elements to which this operation applies, + * or null if not applicable. + */ + protected ICElement[] getElementsToProcess() { + return fElementsToProcess; + } + + /** + * Returns the element to which this operation applies, + * or null if not applicable. + */ + protected ICElement getElementToProcess() { + if (fElementsToProcess == null || fElementsToProcess.length == 0) { + return null; + } + return fElementsToProcess[0]; + } + + /** + * Returns the C Model this operation is operating in. + */ + public ICRoot getCRoot() { + if (fElementsToProcess == null || fElementsToProcess.length == 0) { + return getParentElement().getCRoot(); + } else { + return fElementsToProcess[0].getCRoot(); + } + } + + /** + * Returns the parent element to which this operation applies, + * or null if not applicable. + */ + protected ICElement getParentElement() { + if (fParentElements == null || fParentElements.length == 0) { + return null; + } + return fParentElements[0]; + } + + /** + * Returns the parent elements to which this operation applies, + * or null if not applicable. + */ + protected ICElement[] getParentElements() { + return fParentElements; + } + + /** + * Returns the elements created by this operation. + */ + public ICElement[] getResultElements() { + return fResultElements; + } + + /** + * Creates and returns a subprogress monitor if appropriate. + */ + protected IProgressMonitor getSubProgressMonitor(int workAmount) { + IProgressMonitor sub = null; + if (fMonitor != null) { + sub = new SubProgressMonitor(fMonitor, workAmount, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); + } + return sub; + } + + /** + * Returns the IWorkspace this operation is working in, or + * null if this operation has no elements to process. + */ + protected IWorkspace getWorkspace() { + if (fElementsToProcess != null && fElementsToProcess.length > 0) { + ICProject project = fElementsToProcess[0].getCProject(); + if (project != null) { + return project.getCRoot().getWorkspace(); + } + } + return null; + } + + /** + * Returns whether this operation has performed any resource modifications. + * Returns false if this operation has not been executed yet. + */ + public boolean hasModifiedResource() { + return !this.isReadOnly() && this.hasModifiedResource; + } + + public void internalWorked(double work) { + if (fMonitor != null) { + fMonitor.internalWorked(work); + } + } + + /** + * @see IProgressMonitor + */ + public boolean isCanceled() { + if (fMonitor != null) { + return fMonitor.isCanceled(); + } + return false; + } + + /** + * Returns true if this operation performs no resource modifications, + * otherwise false. Subclasses must override. + */ + public boolean isReadOnly() { + return false; + } + + /** + * Convenience method to move resources + */ + protected void moveResources(IResource[] resources, IPath destinationPath) throws CModelException { + IProgressMonitor subProgressMonitor = null; + if (fMonitor != null) { + subProgressMonitor = new SubProgressMonitor(fMonitor, resources.length, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK); + } + IWorkspace workspace = resources[0].getWorkspace(); + try { + workspace.move(resources, destinationPath, false, subProgressMonitor); + this.hasModifiedResource = true; + } catch (CoreException e) { + throw new CModelException(e); + } + } + + /** + * Creates and returns a new ICElementDelta + * on the C Model. + */ + public CElementDelta newCElementDelta() { + return new CElementDelta(getCRoot()); + } + + /** + * Registers any deltas this operation created, with the + * C Model manager. + */ + protected void registerDeltas() { + if (fDeltas != null && !fNested) { + // hook to ensure working copies remain consistent + //makeWorkingCopiesConsistent(fDeltas); + CModelManager manager= CModelManager.getDefault(); + for (int i= 0; i < fDeltas.length; i++) { + manager.registerCModelDelta(fDeltas[i]); + } + } + } + + /** + * Main entry point for C Model operations. Executes this operation + * and registers any deltas created. + * + * @see IWorkspaceRunnable + * @exception CoreException if the operation fails + */ + public void run(IProgressMonitor monitor) throws CoreException { + try { + fMonitor = monitor; + execute(); + } finally { + registerDeltas(); + } + } + + /** + * @see IProgressMonitor + */ + public void setCanceled(boolean b) { + if (fMonitor != null) { + fMonitor.setCanceled(b); + } + } + + /** + * Sets whether this operation is nested or not. + * @see CreateElementInCUOperation#checkCanceled + */ + protected void setNested(boolean nested) { + fNested = nested; + } + + /** + * @see IProgressMonitor + */ + public void setTaskName(String name) { + if (fMonitor != null) { + fMonitor.setTaskName(name); + } + } + + /** + * @see IProgressMonitor + */ + public void subTask(String name) { + if (fMonitor != null) { + fMonitor.subTask(name); + } + } + /** + * Returns a status indicating if there is any known reason + * this operation will fail. Operations are verified before they + * are run. + * + * Subclasses must override if they have any conditions to verify + * before this operation executes. + * + * @see ICModelStatus + */ + protected ICModelStatus verify() { + return commonVerify(); + } + + /** + * @see IProgressMonitor + */ + public void worked(int work) { + if (fMonitor != null) { + fMonitor.worked(work); + checkCanceled(); + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelStatus.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelStatus.java new file mode 100644 index 00000000000..0e9588f6ea8 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelStatus.java @@ -0,0 +1,259 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.ICModelStatusConstants; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.ICElement; + +import org.eclipse.cdt.core.model.CoreModel; + +/** + * @see ICModelStatus + */ + +public class CModelStatus extends Status implements ICModelStatus, ICModelStatusConstants, IResourceStatus { + + // FIXME: Use the value in the plugin. + private static String PLUGIN_ID = CoreModel.getPluginId(); + + /** + * The elements related to the failure, or null + * if no elements are involved. + */ + protected ICElement[] fElements = new ICElement[0]; + /** + * The path related to the failure, or null + * if no path is involved. + */ + protected IPath fPath; + /** + * The String related to the failure, or null + * if no String is involved. + */ + protected String fString; + /** + * Empty children + */ + protected final static IStatus[] fgEmptyChildren = new IStatus[] {}; + protected IStatus[] fChildren= fgEmptyChildren; + + /** + * Singleton OK object + */ + public static final ICModelStatus VERIFIED_OK = new CModelStatus(OK); + + /** + * Constructs an C model status with no corresponding elements. + */ + public CModelStatus() { + // no code for an multi-status + super(ERROR, PLUGIN_ID, 0, "CModelStatus", null); //$NON-NLS-1$ + } + + /** + * Constructs an C model status with no corresponding elements. + */ + public CModelStatus(int code) { + super(ERROR, PLUGIN_ID, code, "CModelStatus", null); //$NON-NLS-1$ + //fElements= CElementInfo.fgEmptyChildren; + } + + /** + * Constructs an C model status with the given corresponding + * elements. + */ + public CModelStatus(int code, ICElement[] elements) { + super(ERROR, PLUGIN_ID, code, "CModelStatus", null); //$NON-NLS-1$ + fElements= elements; + fPath= null; + } + + /** + * Constructs an C model status with no corresponding elements. + */ + public CModelStatus(int code, String string) { + super(ERROR, PLUGIN_ID, code, "CModelStatus", null); //$NON-NLS-1$ + //fElements= CElementInfo.fgEmptyChildren; + fPath= null; + fString = string; + } + + /** + * Constructs an C model status with no corresponding elements. + */ + public CModelStatus(int code, Throwable throwable) { + super(ERROR, PLUGIN_ID, code, "CModelStatus", throwable); //$NON-NLS-1$ + //fElements= CElementInfo.fgEmptyChildren; + } + + /** + * Constructs an C model status with no corresponding elements. + */ + public CModelStatus(int code, IPath path) { + super(ERROR, PLUGIN_ID, code, "CModelStatus", null); //$NON-NLS-1$ + //fElements= CElementInfo.fgEmptyChildren; + fPath= path; + } + + /** + * Constructs an C model status with the given corresponding + * element. + */ + public CModelStatus(int code, ICElement element) { + this(code, new ICElement[]{element}); + } + + /** + * Constructs an C model status with the given corresponding + * element and string + */ + public CModelStatus(int code, ICElement element, String string) { + this(code, new ICElement[]{element}); + fString= string; + } + + /** + * Constructs an C model status with no corresponding elements. + */ + public CModelStatus(CoreException coreException) { + super(ERROR, PLUGIN_ID, CORE_EXCEPTION, "CModelStatus", coreException); //$NON-NLS-1$ + //fElements= CElementInfo.fgEmptyChildren; + } + + protected int getBits() { + int severity = 1 << (getCode() % 100 / 33); + int category = 1 << ((getCode() / 100) + 3); + return severity | category; + } + + /** + * @see IStatus + */ + public IStatus[] getChildren() { + return fChildren; + } + + /** + * @see ICModelStatus + */ + public ICElement[] getElements() { + return fElements; + } + + /** + * Returns the message that is relevant to the code of this status. + */ + public String getMessage() { + return "Error in C Plugin"; + } + /** + * @see IOperationStatus + */ + public IPath getPath() { + return fPath; + } + + /** + * @see IStatus + */ + public int getSeverity() { + if (fChildren == fgEmptyChildren) return super.getSeverity(); + int severity = -1; + for (int i = 0, max = fChildren.length; i < max; i++) { + int childrenSeverity = fChildren[i].getSeverity(); + if (childrenSeverity > severity) { + severity = childrenSeverity; + } + } + return severity; + } + + /** + * @see ICModelStatus + */ + public String getString() { + return fString; + } + + /** + * @see ICModelStatus + */ + public boolean doesNotExist() { + return getCode() == ELEMENT_DOES_NOT_EXIST; + } + + /** + * @see IStatus + */ + public boolean isMultiStatus() { + return fChildren != fgEmptyChildren; + } + + /** + * @see ICModelStatus + */ + public boolean isOK() { + return getCode() == OK; + } + + /** + * @see IStatus#matches + */ + public boolean matches(int mask) { + if (! isMultiStatus()) { + return matches(this, mask); + } else { + for (int i = 0, max = fChildren.length; i < max; i++) { + if (matches((CModelStatus) fChildren[i], mask)) + return true; + } + return false; + } + } + + /** + * Helper for matches(int). + */ + protected boolean matches(CModelStatus status, int mask) { + int severityMask = mask & 0x7; + int categoryMask = mask & ~0x7; + int bits = status.getBits(); + return ((severityMask == 0) || (bits & severityMask) != 0) && ((categoryMask == 0) || (bits & categoryMask) != 0); + } + + /** + * Creates and returns a new ICModelStatus that is a + * a multi-status status. + * + * @see IStatus#.isMultiStatus() + */ + public static ICModelStatus newMultiStatus(ICModelStatus[] children) { + CModelStatus jms = new CModelStatus(); + jms.fChildren = children; + return jms; + } + + /** + * Returns a printable representation of this exception for debugging + * purposes. + */ + public String toString() { + if (this == VERIFIED_OK){ + return "CModelStatus[OK]"; //$NON-NLS-1$ + } + StringBuffer buffer = new StringBuffer(); + buffer.append("C Model Status ["); //$NON-NLS-1$ + buffer.append(getMessage()); + buffer.append("]"); //$NON-NLS-1$ + return buffer.toString(); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java new file mode 100644 index 00000000000..c41784556fd --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProject.java @@ -0,0 +1,69 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IBinaryContainer; +import org.eclipse.cdt.core.model.IArchiveContainer; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICModelStatusConstants; + +public class CProject extends CResource implements ICProject { + + boolean elfDone = false; + + public CProject (ICElement parent, IProject project) { + super (parent, project, CElement.C_PROJECT); + } + + public IBinaryContainer getBinaryContainer() { + return getCProjectInfo().getBinaryContainer(); + } + + public IArchiveContainer getArchiveContainer() { + return getCProjectInfo().getArchiveContainer(); + } + + public IProject getProject() { + try { + return getUnderlyingResource().getProject(); + } catch (CModelException e) { + e.printStackTrace(); + } + return null; + } + + public ICProject getCProject() { + return this; + } + + public ICElement findElement(IPath path) throws CModelException { + ICElement celem = CModelManager.getDefault().create(path); + if (celem == null) + new CModelStatus(ICModelStatusConstants.INVALID_PATH, path); + return celem; + } + + synchronized protected boolean hasRunElf() { + return elfDone; + } + + synchronized protected void setRunElf(boolean done) { + elfDone = done; + } + + protected CProjectInfo getCProjectInfo() { + return (CProjectInfo)getElementInfo(); + } + + protected CElementInfo createElementInfo() { + return new CProjectInfo(this); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProjectInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProjectInfo.java new file mode 100644 index 00000000000..0a0e1e3e62e --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CProjectInfo.java @@ -0,0 +1,52 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IArchiveContainer; +import org.eclipse.cdt.core.model.IBinaryContainer; + +/** + * Info for ICProject. + */ + +class CProjectInfo extends CResourceInfo { + + private BinaryContainer vBin; + private ArchiveContainer vLib; + + public IBinaryContainer getBinaryContainer() { + if (vBin == null) { + vBin = new BinaryContainer((CProject)getElement()); + addChild(vBin); + } + return vBin; + } + + public IArchiveContainer getArchiveContainer() { + if (vLib == null) { + vLib = new ArchiveContainer((CProject)getElement()); + addChild(vLib); + } + return vLib; + } + + public ICElement[] getChildren() { + // ensure that BinaryContqainer and ArchiveContainer + // have been added as children. Side affect of get methods! + getBinaryContainer(); + getArchiveContainer(); + return super.getChildren(); + } + + /** + */ + public CProjectInfo(CElement element) { + super(element); + vBin = null; + vLib = null; + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResource.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResource.java new file mode 100644 index 00000000000..abb010c5ff1 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResource.java @@ -0,0 +1,40 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.CModelException; + +public abstract class CResource extends Parent { + + public CResource (ICElement parent, IPath path, int type) { + // Check if the file is under the workspace. + this (parent, ResourcesPlugin.getWorkspace().getRoot().getFileForLocation (path), + path.lastSegment(), type); + } + + public CResource (ICElement parent, IResource resource, int type) { + this (parent, resource, resource.getName(), type); + } + + public CResource (ICElement parent, IResource resource, String name, int type) { + super (parent, resource, name, type); + } + + public IResource getUnderlyingResource() throws CModelException { + return resource; + } + + public IResource getCorrespondingResource() throws CModelException { + return resource; + } + + protected abstract CElementInfo createElementInfo (); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResourceInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResourceInfo.java new file mode 100644 index 00000000000..41ec313a1b4 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CResourceInfo.java @@ -0,0 +1,70 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.ICElement; + +/** + */ +public class CResourceInfo extends CElementInfo { + + /** + * Constructs a new C Model Info + */ + protected CResourceInfo(CElement element) { + super(element); + } + + // Always return true, save the unnecessary probing from the Treeviewer. + protected boolean hasChildren () { + return true; + } + + protected ICElement [] getChildren () { + try { + IResource[] resources = null; + IResource res = getElement().getUnderlyingResource(); + if (res != null) { + //System.out.println (" Resource: " + res.getFullPath().toOSString()); + switch(res.getType()) { + case IResource.ROOT: + case IResource.PROJECT: + case IResource.FOLDER: + IContainer container = (IContainer)res; + resources = container.members(false); + break; + + case IResource.FILE: + break; + } + } + + if (resources != null) { + CModelManager factory = CModelManager.getDefault(); + for (int i = 0; i < resources.length; i++) { + // Check for Valid C projects only. + if(resources[i].getType() == IResource.PROJECT) { + IProject proj = (IProject)resources[i]; + if (!factory.hasCNature(proj)) { + continue; + } + } + addChild(factory.create(getElement(), resources[i])); + } + } + } catch (CoreException e) { + //System.out.println (e); + //CPlugin.log (e); + e.printStackTrace(); + } + return super.getChildren(); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRoot.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRoot.java new file mode 100644 index 00000000000..8d573a8b6c7 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRoot.java @@ -0,0 +1,113 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.runtime.IProgressMonitor; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ICRoot; +import org.eclipse.cdt.core.model.CModelException; + +public class CRoot extends CResource implements ICRoot { + + public CRoot(IWorkspaceRoot root) { + super (null, root, root.getName(), ICElement.C_ROOT); + } + + public ICRoot getCModel() { + return this; + } + public ICProject getCProject(String name) { + CModelManager factory = CModelManager.getDefault(); + return (ICProject)factory.create(getWorkspace().getRoot().getProject(name)); + } + + public ICProject[] getCProjects() { + return (ICProject[])getChildren(); + } + + public IWorkspace getWorkspace() { + try { + return getUnderlyingResource().getWorkspace(); + } catch (CModelException e) { + e.printStackTrace(); + } + return null; + } + + public IWorkspaceRoot getRoot() { + try { + return (IWorkspaceRoot)getUnderlyingResource(); + } catch (CModelException e) { + } + return null; + } + + public void copy(ICElement[] elements, ICElement[] containers, ICElement[] siblings, + String[] renamings, boolean replace, IProgressMonitor monitor) throws CModelException { + if (elements != null && elements[0] != null + && elements[0].getCorrespondingResource() != null ) { + runOperation(new CopyResourceElementsOperation(elements, containers, replace), elements, siblings, renamings, monitor); + } else { + throw new CModelException (new CModelStatus()); + //runOperation(new CopyElementsOperation(elements, containers, force), elements, siblings, renamings, monitor); + } + } + + public void delete(ICElement[] elements, boolean force, IProgressMonitor monitor) + throws CModelException { + if (elements != null && elements[0] != null + && elements[0].getCorrespondingResource() != null) { + runOperation(new DeleteResourceElementsOperation(elements, force), monitor); + } else { + throw new CModelException (new CModelStatus()); + //runOperation(new DeleteElementsOperation(elements, force), monitor); + } + } + + public void move(ICElement[] elements, ICElement[] containers, ICElement[] siblings, + String[] renamings, boolean replace, IProgressMonitor monitor) throws CModelException { + if (elements != null && elements[0] != null + && elements[0].getCorrespondingResource() == null) { + runOperation(new MoveResourceElementsOperation(elements, containers, replace), elements, siblings, renamings, monitor); + } else { + throw new CModelException (new CModelStatus()); + //runOperation(new MoveElementsOperation(elements, containers, force), elements, siblings, renamings, monitor); + } + } + + public void rename(ICElement[] elements, ICElement[] destinations, String[] renamings, + boolean force, IProgressMonitor monitor) throws CModelException { + if (elements != null && elements[0] != null + && elements[0].getCorrespondingResource() == null) { + runOperation(new RenameResourceElementsOperation(elements, destinations, + renamings, force), monitor); + } else { + throw new CModelException (new CModelStatus()); + //runOperation(new RenameElementsOperation(elements, containers, renamings, force), monitor); + } + } + + /** + * Configures and runs the MultiOperation. + */ + protected void runOperation(MultiOperation op, ICElement[] elements, ICElement[] siblings, String[] renamings, IProgressMonitor monitor) throws CModelException { + op.setRenamings(renamings); + if (siblings != null) { + for (int i = 0; i < elements.length; i++) { + op.setInsertBefore(elements[i], siblings[i]); + } + } + runOperation(op, monitor); + } + + protected CElementInfo createElementInfo () { + return new CRootInfo(this); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRootInfo.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRootInfo.java new file mode 100644 index 00000000000..7baefdef5c6 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CRootInfo.java @@ -0,0 +1,19 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +/** + * @see ICModel + */ +public class CRootInfo extends CResourceInfo { + + /** + * Constructs a new C Model Info + */ + protected CRootInfo(CElement element) { + super(element); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CopyElementsOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CopyElementsOperation.java new file mode 100644 index 00000000000..80fe7b62e8c --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CopyElementsOperation.java @@ -0,0 +1,218 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ +import java.util.HashMap; +import java.util.Map; + + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.ICModelStatusConstants; +import org.eclipse.cdt.core.model.CModelException; + +/** + * This operation copies/moves a collection of elements from their current + * container to a new container, optionally renaming the + * elements. + *

Notes:

+ * + */ +public class CopyElementsOperation extends MultiOperation { + + private Map fSources = new HashMap(); + + /** + * When executed, this operation will copy the given elements to the + * given containers. The elements and destination containers must be in + * the correct order. If there is > 1 destination, the number of destinations + * must be the same as the number of elements being copied/moved/renamed. + */ + public CopyElementsOperation(ICElement[] elementsToCopy, ICElement[] destContainers, boolean force) { + super(elementsToCopy, destContainers, force); + } + + /** + * When executed, this operation will copy the given elements to the + * given container. + */ + public CopyElementsOperation(ICElement[] elementsToCopy, ICElement destContainer, boolean force) { + this(elementsToCopy, new ICElement[]{destContainer}, force); + } + + /** + * Returns the String to use as the main task name + * for progress monitoring. + */ + protected String getMainTaskName() { + return "operation.copyElementProgress"; //$NON-NLS-1$ + } + + /** + * Returns the nested operation to use for processing this element + */ + protected CModelOperation getNestedOperation(ICElement element) { + //ICElement dest = getDestinationParent(element); + switch (element.getElementType()) { + //case ICElement.C_INCLUDE: + // return new CreateIncludeOperation(element, dest); + //case ICElement.C_FUNCTION_DECLARATION : + // return new CreateFunctionDeclarationOperation(element, dest); + //case ICElement.C_FUNCTION : + // return new CreateFunctionOperation(element, dest); + //case ICElement.C_STRUCTURE : + // return new CreateStructureOperation(element, dest, fForce); + //case ICElement.C_METHOD : + // return new CreateMethodOperation(element, dest, fForce); + //case ICElement.C_FIELD : + // return new CreateFieldOperation(element, dest, fForce); + //case ICElement.C_VARIABLE: + // return new CreateVariableOperation(element, dest); + default : + return null; + } + } + + /** + * Copy/move the element from the source to destination, renaming + * the elements as specified, honoring the collision policy. + * + * @exception CModelException if the operation is unable to + * be completed + */ + protected void processElement(ICElement element) throws CModelException { + CModelOperation op = getNestedOperation(element); + if (op == null) { + return; + } + boolean isInTUOperation = op instanceof CreateElementInTUOperation; + if (isInTUOperation) { + CreateElementInTUOperation inTUop = (CreateElementInTUOperation)op; + ICElement sibling = (ICElement) fInsertBeforeElements.get(element); + if (sibling != null) { + (inTUop).setRelativePosition(sibling, CreateElementInTUOperation.INSERT_BEFORE); + } else if (isRename()) { + ICElement anchor = resolveRenameAnchor(element); + if (anchor != null) { + inTUop.setRelativePosition(anchor, CreateElementInTUOperation.INSERT_AFTER); // insert after so that the anchor is found before when deleted below + } + } + String newName = getNewNameFor(element); + if (newName != null) { + inTUop.setAlteredName(newName); + } + } + executeNestedOperation(op, 1); + + //if (isInTUOperation && isMove()) { + // DeleteElementsOperation deleteOp = new DeleteElementsOperation(new ICElement[] { element }, fForce); + // executeNestedOperation(deleteOp, 1); + //} + } + + /** + * Returns the anchor used for positioning in the destination for + * the element being renamed. For renaming, if no anchor has + * explicitly been provided, the element is anchored in the same position. + */ + private ICElement resolveRenameAnchor(ICElement element) throws CModelException { + IParent parent = (IParent) element.getParent(); + ICElement[] children = parent.getChildren(); + for (int i = 0; i < children.length; i++) { + ICElement child = children[i]; + if (child.equals(element)) { + return child; + } + } + return null; + } + + /** + * Possible failures: + * + */ + protected ICModelStatus verify() { + ICModelStatus status = super.verify(); + if (!status.isOK()) { + return status; + } + if (fRenamingsList != null && fRenamingsList.length != fElementsToProcess.length) { + return new CModelStatus(ICModelStatusConstants.INDEX_OUT_OF_BOUNDS); + } + return CModelStatus.VERIFIED_OK; + } + + /** + * @see MultiOperation + * + * Possible failure codes: + * + */ + protected void verify(ICElement element) throws CModelException { + if (element == null || !element.exists()) + error(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST, element); + + if (element.getElementType() < ICElement.C_UNIT) + error(ICModelStatusConstants.INVALID_ELEMENT_TYPES, element); + + if (element.isReadOnly()) + error(ICModelStatusConstants.READ_ONLY, element); + + ICElement dest = getDestinationParent(element); + verifyDestination(element, dest); + verifySibling(element, dest); + if (fRenamingsList != null) { + verifyRenaming(element); + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CopyResourceElementsOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CopyResourceElementsOperation.java new file mode 100644 index 00000000000..dc88e9d5499 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CopyResourceElementsOperation.java @@ -0,0 +1,250 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICElementDelta; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.ICModelStatusConstants; +import org.eclipse.cdt.core.model.CModelException; + +/** + * This operation copies/moves/renames a collection of resources from their current + * container to a new container, optionally renaming the + * elements. + *

Notes:

+ * + */ +public class CopyResourceElementsOperation extends MultiOperation { + + /** + * The list of new resources created during this operation. + */ + protected ArrayList fCreatedElements; + + /** + * Table specifying deltas for elements being + * copied/moved/renamed. Keyed by elements' project(s), and + * values are the corresponding deltas. + */ + protected Map fDeltasPerProject= new HashMap(1); + + public CopyResourceElementsOperation(ICElement[] src, ICElement[] dst, boolean force) { + super(src, dst, force); + } + + /** + * Returns the CElementDelta for cProject, + * creating it and putting it in fDeltasPerProject if + * it does not exist yet. + */ + private CElementDelta getDeltaFor(ICProject cProject) { + CElementDelta delta = (CElementDelta) fDeltasPerProject.get(cProject); + if (delta == null) { + delta = new CElementDelta(cProject); + fDeltasPerProject.put(cProject, delta); + } + return delta; + } + + /** + * @see MultiOperation + */ + protected String getMainTaskName() { + return "operation.copyResourceProgress"; //$NON-NLS-1$ + } + + /** + * Sets the deltas to register the changes resulting from this operation + * for this source element and its destination. + * If the operation is a cross project operation + * If the operation is rooted in a single project, the delta is rooted in that project + * + */ + protected void prepareDeltas(ICElement sourceElement, ICElement destinationElement) { + ICProject destProject = destinationElement.getCProject(); + if (isMove()) { + ICProject sourceProject = sourceElement.getCProject(); + getDeltaFor(sourceProject).movedFrom(sourceElement, destinationElement); + getDeltaFor(destProject).movedTo(destinationElement, sourceElement); + } else { + getDeltaFor(destProject).added(destinationElement); + } + } + + /** + * Process all of the changed deltas generated by this operation. + */ + protected void processDeltas() { + for (Iterator deltas = this.fDeltasPerProject.values().iterator(); deltas.hasNext();){ + addDelta((ICElementDelta) deltas.next()); + } + } + + /** + * Copies/moves a compilation unit with the name newName + * to the destination package.
+ * The package statement in the compilation unit is updated if necessary. + * The main type of the compilation unit is renamed if necessary. + * + * @exception JavaModelException if the operation is unable to + * complete + */ + private void processResource(ICElement source, ICElement dest) throws CModelException { + String newName = getNewNameFor(source); + String destName = (newName != null) ? newName : source.getElementName(); + + // copy resource + IFile sourceResource = (IFile)source.getCorrespondingResource(); + // can be an IFolder or an IProject + IContainer destFolder = (IContainer)dest.getCorrespondingResource(); + IFile destFile = destFolder.getFile(new Path(destName)); + if (!destFile.equals(sourceResource)) { + try { + if (destFile.exists()) { + if (fForce) { + // we can remove it + deleteResource(destFile, false); + } else { + // abort + throw new CModelException(new CModelStatus(ICModelStatusConstants.NAME_COLLISION)); + } + } + if (this.isMove()) { + sourceResource.move(destFile.getFullPath(), fForce, true, getSubProgressMonitor(1)); + } else { + sourceResource.copy(destFile.getFullPath(), fForce, getSubProgressMonitor(1)); + } + this.hasModifiedResource = true; + } catch (CModelException e) { + throw e; + } catch (CoreException e) { + throw new CModelException(e); + } + + // update new resource content + + // register the correct change deltas + ICElement cdest = CModelManager.getDefault().create(destFile); + prepareDeltas(source, cdest); + fCreatedElements.add(cdest); + //if (newName != null) { + //the main type has been renamed + //String oldName = source.getElementName(); + //oldName = oldName.substring(0, oldName.length() - 5); + //String nName = newName; + //nName = nName.substring(0, nName.length() - 5); + //prepareDeltas(source.getType(oldName), cdest.getType(nName)); + //} + } else { + if (!fForce) { + throw new CModelException(new CModelStatus(ICModelStatusConstants.NAME_COLLISION)); + } + // update new resource content + // in case we do a saveas on the same resource we have to simply update the contents + // see http://dev.eclipse.org/bugs/show_bug.cgi?id=9351 + } + } + + /** + * @see MultiOperation + * This method delegates to processResource or + * processPackageFragmentResource, depending on the type of + * element. + */ + protected void processElement(ICElement element) throws CModelException { + ICElement dest = getDestinationParent(element); + if (element.getCorrespondingResource() != null) { + processResource(element, dest); + //fCreatedElements.add(dest.getCompilationUnit(element.getElementName())); + } else { + throw new CModelException(new CModelStatus(ICModelStatusConstants.INVALID_ELEMENT_TYPES, element)); + } + } + + /** + * @see MultiOperation + * Overridden to allow special processing of CElementDeltas + * and fResultElements. + */ + protected void processElements() throws CModelException { + fCreatedElements = new ArrayList(fElementsToProcess.length); + try { + super.processElements(); + } catch (CModelException cme) { + throw cme; + } finally { + fResultElements = new ICElement[fCreatedElements.size()]; + fCreatedElements.toArray(fResultElements); + processDeltas(); + } + } + + /** + * Possible failures: + * + */ + protected ICModelStatus verify() { + ICModelStatus status = super.verify(); + if (!status.isOK()) { + return status; + } + + if (fRenamingsList != null && fRenamingsList.length != fElementsToProcess.length) { + return new CModelStatus(ICModelStatusConstants.INDEX_OUT_OF_BOUNDS); + } + return CModelStatus.VERIFIED_OK; + } + + /** + * @see MultiOperation + */ + protected void verify(ICElement element) throws CModelException { + if (element == null || !element.exists()) + error(ICModelStatusConstants.ELEMENT_DOES_NOT_EXIST, element); + + if (element.isReadOnly() && (isRename() || isMove())) + error(ICModelStatusConstants.READ_ONLY, element); + + CElement dest = (CElement) getDestinationParent(element); + verifyDestination(element, dest); + if (fRenamings != null) { + verifyRenaming(element); + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateElementInTUOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateElementInTUOperation.java new file mode 100644 index 00000000000..ccb695df1d1 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateElementInTUOperation.java @@ -0,0 +1,415 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.InputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ISourceRange; +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.ICModelStatusConstants; +import org.eclipse.cdt.core.model.CModelException; + +/** + *

This abstract class implements behavior common to CreateElementInCUOperations. + * To create a compilation unit, or an element contained in a compilation unit, the + * source code for the entire compilation unit is updated and saved. + * + *

The element being created can be positioned relative to an existing + * element in the compilation unit via the methods #createAfter + * and #createBefore. By default, the new element is positioned + * as the last child of its parent element. + * + */ +public abstract class CreateElementInTUOperation extends CModelOperation { + + /** + * A constant meaning to position the new element + * as the last child of its parent element. + */ + protected static final int INSERT_LAST = 1; + + /** + * A constant meaning to position the new element + * after the element defined by fAnchorElement. + */ + protected static final int INSERT_AFTER = 2; + + /** + * A constant meaning to position the new element + * before the element defined by fAnchorElement. + */ + protected static final int INSERT_BEFORE = 3; + + /** + * One of the position constants, describing where + * to position the newly created element. + */ + protected int fInsertionPolicy = INSERT_LAST; + + /** + * The element that is being created. + */ + protected ISourceReference fCreatedElement = null;; + + /** + * The element that the newly created element is + * positioned relative to, as described by + * fInsertPosition, or null + * if the newly created element will be positioned + * last. + */ + protected ICElement fAnchorElement = null; + + /** + * A flag indicating whether creation of a new element occurred. + * A request for creating a duplicate element would request in this + * flag being set to false. Ensures that no deltas are generated + * when creation does not occur. + */ + protected boolean fCreationOccurred = true; + + /** + * The position of the element that is being created. + */ + protected int fInsertionPosition = -1; + + /** + * The number of characters the new element replaces, + * or 0 if the new element is inserted, + * or -1 if the new element is append to the end of the CU. + */ + protected int fReplacementLength = -1; + + /** + * Constructs an operation that creates a C Language Element with + * the specified parent, contained within a translation unit. + */ + public CreateElementInTUOperation(ICElement parentElement) { + super(null, new ICElement[]{parentElement}); + initializeDefaultPosition(); + } + + /** + * Only allow cancelling if this operation is not nested. + */ + protected void checkCanceled() { + if (!fNested) { + super.checkCanceled(); + } + } + + /** + * Instructs this operation to position the new element after + * the given sibling, or to add the new element as the last child + * of its parent if null. + */ + public void createAfter(ICElement sibling) { + setRelativePosition(sibling, INSERT_AFTER); + } + + /** + * Instructs this operation to position the new element before + * the given sibling, or to add the new element as the last child + * of its parent if null. + */ + public void createBefore(ICElement sibling) { + setRelativePosition(sibling, INSERT_BEFORE); + } + + /** + * Execute the operation - generate new source for the compilation unit + * and save the results. + * + * @exception CModelException if the operation is unable to complete + */ + protected void executeOperation() throws CModelException { + beginTask(getMainTaskName(), getMainAmountOfWork()); + CElementDelta delta = newCElementDelta(); + ITranslationUnit unit = getTranslationUnit(); + insertElement(); + if (fCreationOccurred) { + //a change has really occurred + IFile file = (IFile)unit.getCorrespondingResource(); + StringBuffer buffer = getContent(file); + switch (fReplacementLength) { + case -1 : + // element is append at the end + buffer.append(fCreatedElement.getSource()); + break; + + case 0 : + // element is inserted + buffer.insert(fInsertionPosition, fCreatedElement.getSource()); + break; + + default : + // element is replacing the previous one + buffer.replace(fInsertionPosition, fReplacementLength, fCreatedElement.getSource()); + } + save(buffer, file); + worked(1); + fResultElements = generateResultHandles(); + //if (!isWorkingCopy) { // if unit is working copy, then save will have already fired the delta + if (unit.getParent().exists()) { + for (int i = 0; i < fResultElements.length; i++) { + delta.added(fResultElements[i]); + } + addDelta(delta); + } // else unit is created outside classpath + // non-java resource delta will be notified by delta processor + //} + } + done(); + } + + /** + * Creates and returns the handle for the element this operation created. + */ + protected abstract ICElement generateResultHandle(); + + /** + * Creates and returns the handles for the elements this operation created. + */ + protected ICElement[] generateResultHandles() throws CModelException { + return new ICElement[]{generateResultHandle()}; + } + + /** + * Returns the compilation unit in which the new element is being created. + */ + protected ITranslationUnit getTranslationUnit() { + return ((ISourceReference)getParentElement()).getTranslationUnit(); + } + + /** + * Returns the amount of work for the main task of this operation for + * progress reporting. + * @see executeOperation() + */ + protected int getMainAmountOfWork(){ + return 2; + } + + /** + * Returns the name of the main task of this operation for + * progress reporting. + * @see executeOperation() + */ + protected abstract String getMainTaskName(); + + /** + * Returns the elements created by this operation. + */ + public ICElement[] getResultElements() { + return fResultElements; + } + + /** + * Sets the default position in which to create the new type + * member. By default, the new element is positioned as the + * last child of the parent element in which it is created. + * Operations that require a different default position must + * override this method. + */ + protected void initializeDefaultPosition() { + } + + /** + * Inserts the given child into the given JDOM, + * based on the position settings of this operation. + * + * @see createAfter(IJavaElement) + * @see createBefore(IJavaElement); + */ + protected void insertElement() throws CModelException { + if (fInsertionPolicy != INSERT_LAST) { + ISourceRange range = ((ISourceReference)fAnchorElement).getSourceRange(); + switch (fInsertionPolicy) { + case INSERT_AFTER: + fReplacementLength = 0; + fInsertionPosition = range.getStartPos() + range.getLength(); + break; + + case INSERT_BEFORE: + fReplacementLength = 0; + fInsertionPosition = range.getStartPos(); + + default: + fReplacementLength = range.getStartPos() + range.getLength(); + fInsertionPosition = range.getStartPos(); + break; + } + return; + } + //add as the last element of the parent + fReplacementLength = -1; + } + + /** + * Sets the name of the DOMNode that will be used to + * create this new element. + * Used by the CopyElementsOperation for renaming. + * Only used for CreateTypeMemberOperation + */ + protected void setAlteredName(String newName) { + } + + /** + * Instructs this operation to position the new element relative + * to the given sibling, or to add the new element as the last child + * of its parent if null. The position + * must be one of the position constants. + */ + protected void setRelativePosition(ICElement sibling, int policy) throws IllegalArgumentException { + if (sibling == null) { + fAnchorElement = null; + fInsertionPolicy = INSERT_LAST; + } else { + fAnchorElement = sibling; + fInsertionPolicy = policy; + } + } + + /** + * Possible failures:

+ * @see ICModelStatus + * @see CNamingConventions + */ + public ICModelStatus verify() { + if (getParentElement() == null) { + return new CModelStatus(ICModelStatusConstants.NO_ELEMENTS_TO_PROCESS); + } + if (fAnchorElement != null) { + ICElement domPresentParent = fAnchorElement.getParent(); + //if (domPresentParent.getElementType() == ICElement.IMPORT_CONTAINER) { + // domPresentParent = domPresentParent.getParent(); + //} + if (!domPresentParent.equals(getParentElement())) { + return new CModelStatus(ICModelStatusConstants.INVALID_SIBLING, fAnchorElement); + } + } + return CModelStatus.VERIFIED_OK; + } + + + StringBuffer getContent(IFile file) throws CModelException { + InputStream stream = null; + try { + stream = new BufferedInputStream(file.getContents(true)); + } catch (CoreException e) { + throw new CModelException(e); + } + try { + char [] b = getInputStreamAsCharArray(stream, -1, null); + return new StringBuffer(b.length).append(b); + } catch (IOException e) { + throw new CModelException(e, ICModelStatusConstants.IO_EXCEPTION); + } finally { + try { + if (stream != null) + stream.close(); + } catch (IOException e) { + } + } + } + + /** + * Returns the given input stream's contents as a character array. + * If a length is specified (ie. if length != -1), only length chars + * are returned. Otherwise all chars in the stream are returned. + * Note this doesn't close the stream. + * @throws IOException if a problem occured reading the stream. + */ + public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding) + throws IOException { + InputStreamReader reader = null; + reader = encoding == null + ? new InputStreamReader(stream) + : new InputStreamReader(stream, encoding); + char[] contents; + if (length == -1) { + contents = new char[0]; + int contentsLength = 0; + int charsRead = -1; + do { + int available = stream.available(); + + // resize contents if needed + if (contentsLength + available > contents.length) { + System.arraycopy( + contents, + 0, + contents = new char[contentsLength + available], + 0, + contentsLength); + } + + // read as many chars as possible + charsRead = reader.read(contents, contentsLength, available); + + if (charsRead > 0) { + // remember length of contents + contentsLength += charsRead; + } + } while (charsRead > 0); + + // resize contents if necessary + if (contentsLength < contents.length) { + System.arraycopy( + contents, + 0, + contents = new char[contentsLength], + 0, + contentsLength); + } + } else { + contents = new char[length]; + int len = 0; + int readSize = 0; + while ((readSize != -1) && (len != length)) { + // See PR 1FMS89U + // We record first the read size. In this case len is the actual read size. + len += readSize; + readSize = reader.read(contents, len, length - len); + } + // See PR 1FMS89U + // Now we need to resize in case the default encoding used more than one byte for each + // character + if (len != length) + System.arraycopy(contents, 0, (contents = new char[len]), 0, len); + } + + return contents; + } + + void save (StringBuffer buffer, IFile file) throws CModelException { + byte[] bytes = buffer.toString().getBytes(); + ByteArrayInputStream stream = new ByteArrayInputStream(bytes); + // use a platform operation to update the resource contents + try { + boolean force = true; + file.setContents(stream, force, true, null); // record history + } catch (CoreException e) { + throw new CModelException(e); + } + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateFieldOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateFieldOperation.java new file mode 100644 index 00000000000..cae08069224 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateFieldOperation.java @@ -0,0 +1,74 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IStructure; +import org.eclipse.cdt.core.model.ICModelStatus; +/** + *

This operation creates a field declaration in a type. + * + *

Required Attributes:

+ */ +public class CreateFieldOperation extends CreateMemberOperation { + /** + * When executed, this operation will create a field with the given name + * in the given type with the specified source. + * + *

By default the new field is positioned after the last existing field + * declaration, or as the first member in the type if there are no + * field declarations. + */ + public CreateFieldOperation(IStructure parentElement, String source, boolean force) { + super(parentElement, source, force); + } + + /** + * @see CreateElementInCUOperation#getMainTaskName + */ + public String getMainTaskName(){ + return "operation.createFieldProgress"; //$NON-NLS-1$ + } + + /** + * By default the new field is positioned after the last existing field + * declaration, or as the first member in the type if there are no + * field declarations. + */ + protected void initializeDefaultPosition() { + IStructure parentElement = getStructure(); + //try { + ICElement[] elements = parentElement.getFields(); + if (elements != null && elements.length > 0) { + createAfter(elements[elements.length - 1]); + } else { + elements = parentElement.getChildren(); + if (elements != null && elements.length > 0) { + createBefore(elements[0]); + } + } + //} catch (CModelException e) { + //} + } + + /** + * @see CreateElementInCUOperation#generateResultHandle + */ + protected ICElement generateResultHandle() { + return getStructure().getField(fSource); + } + + /** + * @see CreateTypeMemberOperation#verifyNameCollision + */ + protected ICModelStatus verifyNameCollision() { + return CModelStatus.VERIFIED_OK; + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateFunctionDeclarationOperation.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateFunctionDeclarationOperation.java new file mode 100644 index 00000000000..d00f25c0167 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CreateFunctionDeclarationOperation.java @@ -0,0 +1,96 @@ +package org.eclipse.cdt.internal.core.model; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IInclude; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.core.model.ICModelStatus; +import org.eclipse.cdt.core.model.CModelException; + +/** + *

This operation adds an include declaration to an existing translation unit. + * If the translation unit already includes the specified include declaration, + * the include is not generated (it does not generate duplicates). + * + *

Required Attributes:

+ */ +public class CreateFunctionDeclarationOperation extends CreateElementInTUOperation { + + /** + * The name of the include to be created. + */ + protected String fFunction; + + /** + * When executed, this operation will add an include to the given translation unit. + */ + public CreateFunctionDeclarationOperation(String function, ITranslationUnit parentElement) { + super(parentElement); + fFunction = function; + } + + /** + * @see CreateElementInCUOperation#generateResultHandle + */ + protected ICElement generateResultHandle() { + try { + return getTranslationUnit().getElement(fFunction); + } catch (CModelException e) { + } + return null; + } + + /** + * @see CreateElementInCUOperation#getMainTaskName + */ + public String getMainTaskName(){ + return "operation.createIncludeProgress"; //$NON-NLS-1$ + } + + /** + * Sets the correct position for the new include: