| 1 | package org.axdt.as3.imp.builders; |
|---|
| 2 | |
|---|
| 3 | import java.util.HashMap; |
|---|
| 4 | |
|---|
| 5 | import org.axdt.as3.AS3Plugin; |
|---|
| 6 | import org.axdt.as3.imp.parser.AS3ParseController; |
|---|
| 7 | import org.axdt.as3.preferences.AS3Preferences; |
|---|
| 8 | import org.axdt.as3.util.AS3Util; |
|---|
| 9 | import org.eclipse.core.resources.IContainer; |
|---|
| 10 | import org.eclipse.core.resources.IFile; |
|---|
| 11 | import org.eclipse.core.resources.IResource; |
|---|
| 12 | import org.eclipse.core.runtime.IPath; |
|---|
| 13 | import org.eclipse.core.runtime.IProgressMonitor; |
|---|
| 14 | import org.eclipse.core.runtime.content.IContentDescription; |
|---|
| 15 | import org.eclipse.imp.builder.BuilderBase; |
|---|
| 16 | import org.eclipse.imp.builder.BuilderUtils; |
|---|
| 17 | import org.eclipse.imp.builder.MarkerCreator; |
|---|
| 18 | import org.eclipse.imp.language.Language; |
|---|
| 19 | import org.eclipse.imp.language.LanguageRegistry; |
|---|
| 20 | import org.eclipse.imp.model.ISourceProject; |
|---|
| 21 | import org.eclipse.imp.model.ModelFactory; |
|---|
| 22 | import org.eclipse.imp.model.ModelFactory.ModelException; |
|---|
| 23 | import org.eclipse.imp.runtime.PluginBase; |
|---|
| 24 | import org.eclipse.jface.preference.IPreferenceStore; |
|---|
| 25 | |
|---|
| 26 | /** |
|---|
| 27 | * A builder may be activated on a file containin AS3 code every time it has |
|---|
| 28 | * changed (when "Build automatically" is on), or when the programmer chooses to |
|---|
| 29 | * "Build" a project. |
|---|
| 30 | */ |
|---|
| 31 | public class AS3Builder extends BuilderBase { |
|---|
| 32 | |
|---|
| 33 | public static final String BUILDER_ID = AS3Plugin.PLUGIN_ID + ".imp.builder"; |
|---|
| 34 | public static final String PROBLEM_MARKER_ID = AS3Plugin.PLUGIN_ID + ".imp.builder.problem"; |
|---|
| 35 | public static final Language LANGUAGE = LanguageRegistry.findLanguage(AS3Plugin.LANGUAGE); |
|---|
| 36 | private HashMap<IPath, AS3ParseController> files; |
|---|
| 37 | |
|---|
| 38 | public AS3Builder() { |
|---|
| 39 | super(); |
|---|
| 40 | files = new HashMap<IPath, AS3ParseController>(); |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | protected PluginBase getPlugin() { |
|---|
| 44 | return AS3Plugin.getDefault(); |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | protected String getErrorMarkerID() { |
|---|
| 48 | return PROBLEM_MARKER_ID; |
|---|
| 49 | } |
|---|
| 50 | |
|---|
| 51 | protected String getWarningMarkerID() { |
|---|
| 52 | return PROBLEM_MARKER_ID; |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | protected String getInfoMarkerID() { |
|---|
| 56 | return PROBLEM_MARKER_ID; |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | /** |
|---|
| 60 | * Decide whether a file needs to be build using this builder. Note that |
|---|
| 61 | * <code>isNonRootSourceFile()</code> and <code>isSourceFile()</code> |
|---|
| 62 | * should never return true for the same file. |
|---|
| 63 | * |
|---|
| 64 | * @return true if an arbitrary file is a AS3 source file. |
|---|
| 65 | */ |
|---|
| 66 | protected boolean isSourceFile(IFile file) { |
|---|
| 67 | IPath path = file.getRawLocation(); |
|---|
| 68 | if (path == null) return false; |
|---|
| 69 | IContainer sourceFolder = AS3Util.getSourceFolder(file); |
|---|
| 70 | |
|---|
| 71 | if (sourceFolder == null) return false; |
|---|
| 72 | |
|---|
| 73 | return LANGUAGE.hasExtension(path.getFileExtension()); |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | /** |
|---|
| 77 | * Decide whether or not to scan a file for dependencies. Note: |
|---|
| 78 | * <code>isNonRootSourceFile()</code> and <code>isSourceFile()</code> |
|---|
| 79 | * should never return true for the same file. |
|---|
| 80 | * |
|---|
| 81 | * @return true if the given file is a source file that this builder should |
|---|
| 82 | * scan for dependencies, but not compile as a top-level compilation |
|---|
| 83 | * unit. |
|---|
| 84 | */ |
|---|
| 85 | protected boolean isNonRootSourceFile(IFile resource) { |
|---|
| 86 | return false; |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | /** |
|---|
| 90 | * Collects compilation-unit dependencies for the given file, and records |
|---|
| 91 | * them via calls to <code>fDependency.addDependency()</code>. |
|---|
| 92 | */ |
|---|
| 93 | protected void collectDependencies(IFile file) { |
|---|
| 94 | // TODO: implement dependency collector |
|---|
| 95 | // fDependencyInfo.addDependency(fromPath, uponPath); |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | /** |
|---|
| 99 | * @return true if this resource identifies the output folder |
|---|
| 100 | */ |
|---|
| 101 | protected boolean isOutputFolder(IResource resource) { |
|---|
| 102 | IPreferenceStore store = AS3Preferences.getInstance().getProjectStore(resource); |
|---|
| 103 | String deployPart = store.getString(AS3Preferences.DEPLOY_PATH); |
|---|
| 104 | IPath fullPath = resource.getFullPath(); |
|---|
| 105 | return fullPath.toPortableString().endsWith(deployPart); |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | /** |
|---|
| 109 | * Compile one AS3 file. |
|---|
| 110 | * It will not actually compile, but analyze and index the model. |
|---|
| 111 | */ |
|---|
| 112 | protected void compile(final IFile file, IProgressMonitor monitor) { |
|---|
| 113 | try { |
|---|
| 114 | |
|---|
| 115 | AS3ParseController parse = getParseController(file); |
|---|
| 116 | |
|---|
| 117 | MarkerCreator marker = new MarkerCreator(file, parse, PROBLEM_MARKER_ID); |
|---|
| 118 | parse.getAnnotationTypeInfo().addProblemMarkerType(getErrorMarkerID()); |
|---|
| 119 | |
|---|
| 120 | ISourceProject sourceProject = ModelFactory.open(file.getProject()); |
|---|
| 121 | IPath path = file.getProjectRelativePath(); |
|---|
| 122 | parse.initialize(path, sourceProject, marker); |
|---|
| 123 | boolean hasBom = false; |
|---|
| 124 | try { |
|---|
| 125 | IContentDescription info = file.getContentDescription(); |
|---|
| 126 | hasBom = info != null && null != info.getProperty(IContentDescription.BYTE_ORDER_MARK); |
|---|
| 127 | } catch (Exception e) { /* ignore */} |
|---|
| 128 | String contents = BuilderUtils.getFileContents(file); |
|---|
| 129 | if (hasBom) { |
|---|
| 130 | // file info says there is a bom |
|---|
| 131 | if (contents.charAt(0)==0xfeff) { |
|---|
| 132 | // first char is misread utf8 char |
|---|
| 133 | contents = contents.substring(1); |
|---|
| 134 | } |
|---|
| 135 | } |
|---|
| 136 | parse.parse(contents, true, monitor); |
|---|
| 137 | |
|---|
| 138 | } catch (ModelException e) { |
|---|
| 139 | getPlugin().logException( |
|---|
| 140 | "Example builder returns without parsing due to a ModelException", e); |
|---|
| 141 | } |
|---|
| 142 | } |
|---|
| 143 | |
|---|
| 144 | private AS3ParseController getParseController(IFile file) { |
|---|
| 145 | IPath path = file.getFullPath(); |
|---|
| 146 | AS3ParseController controller = files.get(path); |
|---|
| 147 | if (controller == null) { |
|---|
| 148 | controller = new AS3ParseController(); |
|---|
| 149 | files.put(path, controller); |
|---|
| 150 | } else { |
|---|
| 151 | AS3Plugin.getDefault().debug("reusing builder parse controller for "+ path); |
|---|
| 152 | } |
|---|
| 153 | return controller; |
|---|
| 154 | } |
|---|
| 155 | } |
|---|