├── .classpath ├── .gitattributes ├── .gitignore ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── META-INF └── MANIFEST.MF ├── README.md ├── build.properties ├── icons ├── bullet_black.png ├── bullet_blue.png ├── bullet_green.png ├── bullet_orange.png ├── bullet_pink.png ├── bullet_purple.png ├── bullet_red.png ├── bullet_star.png ├── bullet_yellow.png ├── frege_default_image.gif ├── frege_default_outline_item.gif ├── frege_file.gif ├── frege_file_error.gif ├── frege_file_warning.gif ├── import.png ├── package.png ├── page_green.png ├── page_info.png ├── page_red.png ├── page_warning.png ├── tag.png ├── tag_blue.png ├── tag_blue_add.png ├── tag_blue_delete.png ├── tag_green.png ├── tag_orange.png ├── tag_outline.png ├── tag_pink.png ├── tag_purple.png ├── tag_red.png └── tag_yellow.png ├── lib └── hint.txt ├── plugin.xml └── src └── frege ├── FregePlugin.java ├── IFregeResources.java └── imp ├── AutoEditStrategy.java ├── actions └── EnableFregeNature.java ├── builders ├── FregeBuilder.java ├── FregeBuilderBase.java └── FregeNature.java ├── contentProposer └── ContentProposer.java ├── documentation └── FregeDocumentationProvider.java ├── editorActions └── FregeEditorActionContributions.java ├── hoverHelper └── FregeHoverHelper.java ├── parser ├── FregeParseController.java └── FregeSourcePositionLocator.java ├── preferences ├── FregeInstancePreferencesTab.java ├── FregePreferencesConstants.java ├── FregePreferencesInitializer.java ├── FregePreferencesPage.java └── frege.pfsp.txt ├── referenceResolvers └── FregeReferenceResolver.java ├── tokenColorer └── FregeTokenColorer.java ├── tree ├── CategoryItem.java ├── FregeLabelProvider.java ├── FregeTreeModelBuilder.java ├── ITreeItem.java ├── ImportItem.java ├── PackageItem.java └── SymbolItem.java └── wizards ├── FregeModuleWizard.java ├── FregeProjectWizard.java ├── NewFregeModuleWizardPage.java ├── NewFregeProjectWizardPageOne.java └── NewFregeProjectWizardPageTwo.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | text=auto 3 | 4 | *.jar binary 5 | *.png binary 6 | *.jpg binary 7 | *.jpeg binary 8 | *.ico binary 9 | *.class binary 10 | 11 | *.pl text 12 | *.fr text 13 | *.java text 14 | *.y text 15 | Makefile text 16 | *.mk text 17 | 18 | # Custom for Visual Studio 19 | *.cs diff=csharp 20 | *.sln merge=union 21 | *.csproj merge=union 22 | *.vbproj merge=union 23 | *.fsproj merge=union 24 | *.dbproj merge=union 25 | 26 | # Standard to msysgit 27 | *.doc diff=astextplain 28 | *.DOC diff=astextplain 29 | *.docx diff=astextplain 30 | *.DOCX diff=astextplain 31 | *.dot diff=astextplain 32 | *.DOT diff=astextplain 33 | *.pdf diff=astextplain 34 | *.PDF diff=astextplain 35 | *.rtf diff=astextplain 36 | *.RTF diff=astextplain 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ########################## 2 | # those should be ignored 3 | ########################## 4 | *.class 5 | *.jar 6 | src/frege/IO.java 7 | src/frege/Version.java 8 | src/frege/List.java 9 | src/frege/MD.java 10 | src/frege/Prelude.java 11 | src/frege/PreludeProperties.java 12 | src/frege/RT.java 13 | src/frege/Scrap.java 14 | src/frege/compiler/ 15 | src/frege/control/ 16 | src/frege/data/ 17 | src/frege/j/ 18 | src/frege/lib/ 19 | src/frege/prelude/ 20 | src/frege/rt/ 21 | src/frege/runtime/ 22 | src/frege/tools/ 23 | 24 | 25 | ################# 26 | ## Eclipse 27 | ################# 28 | 29 | *.pydevproject 30 | .project 31 | .metadata 32 | bin/ 33 | tmp/ 34 | *.tmp 35 | *.bak 36 | *.swp 37 | *~.nib 38 | local.properties 39 | .settings/ 40 | .loadpath 41 | 42 | # External tool builders 43 | .externalToolBuilders/ 44 | 45 | # Locally stored "Eclipse launch configurations" 46 | *.launch 47 | 48 | # CDT-specific 49 | .cproject 50 | 51 | # PDT-specific 52 | .buildpath 53 | 54 | 55 | ############ 56 | ## Windows 57 | ############ 58 | 59 | # Windows image file caches 60 | Thumbs.db 61 | 62 | # Folder config file 63 | Desktop.ini 64 | 65 | 66 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | FregIDE 4 | IDE for the Frege Programing Language 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.pde.ManifestBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.pde.SchemaBuilder 20 | 21 | 22 | 23 | 24 | 25 | org.eclipse.pde.PluginNature 26 | org.eclipse.jdt.core.javanature 27 | org.eclipse.imp.metatooling.sanityNature 28 | org.eclipse.imp.prefspecs.nature 29 | org.eclipse.imp.smapifier.smapinature 30 | 31 | 32 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.compliance=1.8 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 7 | org.eclipse.jdt.core.compiler.source=1.8 8 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: FregIDE 4 | Bundle-SymbolicName: frege.ide;singleton:=true 5 | Bundle-Version: 3.25.42 6 | Bundle-Vendor: Ingo Wechsung 7 | Bundle-RequiredExecutionEnvironment: JavaSE-1.8 8 | Require-Bundle: impulse;bundle-version="0.1.0", 9 | org.eclipse.core.runtime, 10 | org.eclipse.core.resources, 11 | org.eclipse.jface.text, 12 | org.eclipse.jdt.core, 13 | org.eclipse.jdt.ui, 14 | org.eclipse.ui, 15 | org.eclipse.ui.ide, 16 | org.eclipse.ui.editors, 17 | org.eclipse.ui.workbench.texteditor 18 | Bundle-Activator: frege.FregePlugin 19 | Bundle-ActivationPolicy: lazy 20 | Export-Package: frege;uses:="impulse,org.osgi.framework" 21 | Eclipse-LazyStart: true 22 | Bundle-ClassPath: bin/, 23 | lib/fregec.jar, 24 | . 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | What is fregIDE? 2 | ================ 3 | 4 | *fregIDE* is an Eclipse plugin that supports the [frege programming language](https://github.com/Frege/). 5 | 6 | You can install or upgrade *fregIDE* from the 7 | installation/upgrade site at http://www.frege-lang.org/fregide/. 8 | 9 | **UPDATE** It has come to my attention that the link above seems to have problems at times, like 10 | 11 | - eclipse complains it is not an update site 12 | - the download goes very slow and even times out (see also [Issue#10](https://github.com/Frege/eclipse-plugin/issues/10)) 13 | 14 | If you experience the same, try this [alternative URL](https://raw.githubusercontent.com/Frege/frege.github.com/master/fregide). 15 | 16 | Please also read [the tutorial](https://github.com/Frege/eclipse-plugin/wiki/fregIDE-Tutorial) that describes the installation in detail. 17 | 18 | 19 | What does it look like? 20 | ======================= 21 | 22 | ![Here is a Screenshot](https://github.com/Frege/frege/wiki/FregIDE-Snapshot.png) 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /build.properties: -------------------------------------------------------------------------------- 1 | source.. = src/ 2 | output.. = bin/ 3 | bin.includes = META-INF/,\ 4 | plugin.xml,\ 5 | icons/,\ 6 | ./bin/,\ 7 | lib/fregec.jar 8 | jars.compile.order = . 9 | -------------------------------------------------------------------------------- /icons/bullet_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_black.png -------------------------------------------------------------------------------- /icons/bullet_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_blue.png -------------------------------------------------------------------------------- /icons/bullet_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_green.png -------------------------------------------------------------------------------- /icons/bullet_orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_orange.png -------------------------------------------------------------------------------- /icons/bullet_pink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_pink.png -------------------------------------------------------------------------------- /icons/bullet_purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_purple.png -------------------------------------------------------------------------------- /icons/bullet_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_red.png -------------------------------------------------------------------------------- /icons/bullet_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_star.png -------------------------------------------------------------------------------- /icons/bullet_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/bullet_yellow.png -------------------------------------------------------------------------------- /icons/frege_default_image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/frege_default_image.gif -------------------------------------------------------------------------------- /icons/frege_default_outline_item.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/frege_default_outline_item.gif -------------------------------------------------------------------------------- /icons/frege_file.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/frege_file.gif -------------------------------------------------------------------------------- /icons/frege_file_error.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/frege_file_error.gif -------------------------------------------------------------------------------- /icons/frege_file_warning.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/frege_file_warning.gif -------------------------------------------------------------------------------- /icons/import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/import.png -------------------------------------------------------------------------------- /icons/package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/package.png -------------------------------------------------------------------------------- /icons/page_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/page_green.png -------------------------------------------------------------------------------- /icons/page_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/page_info.png -------------------------------------------------------------------------------- /icons/page_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/page_red.png -------------------------------------------------------------------------------- /icons/page_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/page_warning.png -------------------------------------------------------------------------------- /icons/tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag.png -------------------------------------------------------------------------------- /icons/tag_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_blue.png -------------------------------------------------------------------------------- /icons/tag_blue_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_blue_add.png -------------------------------------------------------------------------------- /icons/tag_blue_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_blue_delete.png -------------------------------------------------------------------------------- /icons/tag_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_green.png -------------------------------------------------------------------------------- /icons/tag_orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_orange.png -------------------------------------------------------------------------------- /icons/tag_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_outline.png -------------------------------------------------------------------------------- /icons/tag_pink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_pink.png -------------------------------------------------------------------------------- /icons/tag_purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_purple.png -------------------------------------------------------------------------------- /icons/tag_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_red.png -------------------------------------------------------------------------------- /icons/tag_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Frege/eclipse-plugin/739d1a7c984045f01929901ee2ea8efa920d11a1/icons/tag_yellow.png -------------------------------------------------------------------------------- /lib/hint.txt: -------------------------------------------------------------------------------- 1 | Please make a link (or copy) the frege compiler and library jar 2 | under the name fregec.jar here, e.g.: 3 | 4 | ln -s ~/Downloads/frege3.20.99.jar fregec.jar 5 | 6 | 7 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 12 | 13 | 14 | 17 | 20 | 21 | 22 | 24 | 29 | 30 | 31 | 33 | 35 | 36 | 37 | 39 | 43 | 44 | 45 | 47 | 53 | 54 | 60 | 61 | 64 | 65 | 66 | 70 | 72 | 74 | 75 | 76 | 77 | 81 | 83 | 84 | 85 | 87 | 88 | 89 | 90 | 94 | 96 | 97 | 99 | 100 | 101 | 103 | 108 | 113 | 114 | 115 | 116 | 118 | 121 | 122 | 123 | 125 | 128 | 129 | 130 | 132 | 135 | 136 | 137 | 139 | 142 | 143 | 144 | 146 | 149 | 150 | 151 | 153 | 156 | 157 | 158 | 160 | 163 | 164 | 165 | 169 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /src/frege/FregePlugin.java: -------------------------------------------------------------------------------- 1 | package frege; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.security.CodeSource; 6 | import java.security.ProtectionDomain; 7 | 8 | import io.usethesource.impulse.runtime.PluginBase; 9 | import org.osgi.framework.BundleContext; 10 | 11 | public class FregePlugin extends PluginBase { 12 | 13 | public static final String kPluginID = "frege.ide"; 14 | public static final String kLanguageID = "frege"; 15 | public static String fregeLib = null; 16 | 17 | /** 18 | * The unique instance of this plugin class 19 | */ 20 | protected static FregePlugin sPlugin; 21 | 22 | public static FregePlugin getInstance() { 23 | if (sPlugin == null) 24 | new FregePlugin(); 25 | return sPlugin; 26 | } 27 | 28 | public FregePlugin() { 29 | super(); 30 | sPlugin = this; 31 | try { 32 | fregeLib = getFregeLib(); 33 | } catch (Exception exc) { 34 | fregeLib = "./lib/fregec.jar"; 35 | } 36 | } 37 | 38 | public void start(BundleContext context) throws Exception { 39 | super.start(context); 40 | } 41 | 42 | /** 43 | * get the path name of the Frege Standard Library 44 | * @throws IOException 45 | */ 46 | public String getFregeLib() throws IOException { 47 | if (fregeLib == null) { 48 | final ProtectionDomain pd = this.getClass().getProtectionDomain(); 49 | final CodeSource cs = pd.getCodeSource(); 50 | URL xurl = cs.getLocation(); 51 | java.io.File it = new java.io.File (xurl.getPath()); 52 | fregeLib = it.getCanonicalPath() + "/lib/fregec.jar"; 53 | fregeLib = java.util.regex.Pattern.compile("\\\\").matcher(fregeLib).replaceAll("/"); 54 | System.err.println(kPluginID + ": " + xurl); 55 | } 56 | return fregeLib; 57 | } 58 | 59 | @Override 60 | public String getID() { 61 | return kPluginID; 62 | } 63 | 64 | @Override 65 | public String getLanguageID() { 66 | return kLanguageID; 67 | } 68 | 69 | // Definitions for image management 70 | 71 | public static final org.eclipse.core.runtime.IPath ICONS_PATH = new org.eclipse.core.runtime.Path( 72 | "icons/"); //$NON-NLS-1$("icons/"); //$NON-NLS-1$ 73 | 74 | protected void initializeImageRegistry( 75 | org.eclipse.jface.resource.ImageRegistry reg) { 76 | org.osgi.framework.Bundle bundle = getBundle(); 77 | org.eclipse.core.runtime.IPath path = ICONS_PATH 78 | .append("tag_outline.png");//$NON-NLS-1$ 79 | org.eclipse.jface.resource.ImageDescriptor imageDescriptor = createImageDescriptor( 80 | bundle, path); 81 | reg.put(IFregeResources.FREGE_DEFAULT_IMAGE, imageDescriptor); 82 | 83 | path = ICONS_PATH.append("bullet_star.png");//$NON-NLS-1$ 84 | imageDescriptor = createImageDescriptor(bundle, path); 85 | reg.put(IFregeResources.FREGE_DEFAULT_OUTLINE_ITEM, imageDescriptor); 86 | 87 | path = ICONS_PATH.append("package.png");//$NON-NLS-1$ 88 | imageDescriptor = createImageDescriptor(bundle, path); 89 | reg.put(IFregeResources.FREGE_PACKAGE_OUTLINE_ITEM, imageDescriptor); 90 | 91 | path = ICONS_PATH.append("import.png");//$NON-NLS-1$ 92 | imageDescriptor = createImageDescriptor(bundle, path); 93 | reg.put(IFregeResources.FREGE_IMPORT_OUTLINE_ITEM, imageDescriptor); 94 | 95 | path = ICONS_PATH.append("bullet_pink.png");//$NON-NLS-1$ 96 | imageDescriptor = createImageDescriptor(bundle, path); 97 | reg.put(IFregeResources.FREGE_TYPE_OUTLINE_ITEM, imageDescriptor); 98 | 99 | path = ICONS_PATH.append("bullet_purple.png");//$NON-NLS-1$ 100 | imageDescriptor = createImageDescriptor(bundle, path); 101 | reg.put(IFregeResources.FREGE_CLASS_OUTLINE_ITEM, imageDescriptor); 102 | 103 | path = ICONS_PATH.append("bullet_orange.png");//$NON-NLS-1$ 104 | imageDescriptor = createImageDescriptor(bundle, path); 105 | reg.put(IFregeResources.FREGE_INST_OUTLINE_ITEM, imageDescriptor); 106 | 107 | path = ICONS_PATH.append("bullet_red.png");//$NON-NLS-1$ 108 | imageDescriptor = createImageDescriptor(bundle, path); 109 | reg.put(IFregeResources.FREGE_DATA_OUTLINE_ITEM, imageDescriptor); 110 | 111 | path = ICONS_PATH.append("bullet_yellow.png");//$NON-NLS-1$ 112 | imageDescriptor = createImageDescriptor(bundle, path); 113 | reg.put(IFregeResources.FREGE_CON_OUTLINE_ITEM, imageDescriptor); 114 | 115 | path = ICONS_PATH.append("bullet_green.png");//$NON-NLS-1$ 116 | imageDescriptor = createImageDescriptor(bundle, path); 117 | reg.put(IFregeResources.FREGE_VAR_OUTLINE_ITEM, imageDescriptor); 118 | 119 | path = ICONS_PATH.append("bullet_blue.png");//$NON-NLS-1$ 120 | imageDescriptor = createImageDescriptor(bundle, path); 121 | reg.put(IFregeResources.FREGE_LOCAL_OUTLINE_ITEM, imageDescriptor); 122 | 123 | path = ICONS_PATH.append("bullet_black.png");//$NON-NLS-1$ 124 | imageDescriptor = createImageDescriptor(bundle, path); 125 | reg.put(IFregeResources.FREGE_LINK_OUTLINE_ITEM, imageDescriptor); 126 | 127 | // path = ICONS_PATH.append("frege_file.gif");//$NON-NLS-1$ 128 | path = ICONS_PATH.append("page_green.png");//$NON-NLS-1$ 129 | imageDescriptor = createImageDescriptor(bundle, path); 130 | reg.put(IFregeResources.FREGE_FILE, imageDescriptor); 131 | 132 | path = ICONS_PATH.append("page_warning.png");//$NON-NLS-1$ 133 | imageDescriptor = createImageDescriptor(bundle, path); 134 | reg.put(IFregeResources.FREGE_FILE_WARNING, imageDescriptor); 135 | 136 | path = ICONS_PATH.append("page_info.png");//$NON-NLS-1$ 137 | imageDescriptor = createImageDescriptor(bundle, path); 138 | reg.put(IFregeResources.FREGE_FILE_INFO, imageDescriptor); 139 | 140 | path = ICONS_PATH.append("page_red.png");//$NON-NLS-1$ 141 | imageDescriptor = createImageDescriptor(bundle, path); 142 | reg.put(IFregeResources.FREGE_FILE_ERROR, imageDescriptor); 143 | } 144 | 145 | public static org.eclipse.jface.resource.ImageDescriptor createImageDescriptor( 146 | org.osgi.framework.Bundle bundle, 147 | org.eclipse.core.runtime.IPath path) { 148 | java.net.URL url = org.eclipse.core.runtime.FileLocator.find(bundle, 149 | path, null); 150 | if (url != null) { 151 | return org.eclipse.jface.resource.ImageDescriptor 152 | .createFromURL(url); 153 | } 154 | return null; 155 | } 156 | 157 | // Definitions for image management end 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/frege/IFregeResources.java: -------------------------------------------------------------------------------- 1 | package frege; 2 | 3 | public interface IFregeResources { 4 | 5 | // Definitions for label provider 6 | 7 | public static final String FREGE_DEFAULT_IMAGE = "frege_default_image"; 8 | 9 | public static final String FREGE_DEFAULT_OUTLINE_ITEM = "frege_default_outline_item"; 10 | 11 | public static final String FREGE_PACKAGE_OUTLINE_ITEM = "frege_package_outline_item"; 12 | public static final String FREGE_IMPORT_OUTLINE_ITEM = "frege_import_outline_item"; 13 | public static final String FREGE_TYPE_OUTLINE_ITEM = "frege_type_outlline_item"; 14 | public static final String FREGE_CLASS_OUTLINE_ITEM = "frege_class_outlline_item"; 15 | public static final String FREGE_INST_OUTLINE_ITEM = "frege_inst_outlline_item"; 16 | public static final String FREGE_DATA_OUTLINE_ITEM = "frege_data_outlline_item"; 17 | public static final String FREGE_VAR_OUTLINE_ITEM = "frege_var_outlline_item"; 18 | public static final String FREGE_LOCAL_OUTLINE_ITEM = "frege_local_outlline_item"; 19 | public static final String FREGE_CON_OUTLINE_ITEM = "frege_con_outlline_item"; 20 | public static final String FREGE_LINK_OUTLINE_ITEM = "frege_link_outlline_item"; 21 | 22 | public static final String FREGE_FILE = "frege_file"; 23 | 24 | public static final String FREGE_FILE_WARNING = "frege_file_warning"; 25 | 26 | public static final String FREGE_FILE_ERROR = "frege_file_error"; 27 | 28 | public static final String FREGE_FILE_INFO = "frege_file_info"; 29 | 30 | // Definitions for label provider end 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/frege/imp/AutoEditStrategy.java: -------------------------------------------------------------------------------- 1 | package frege.imp; 2 | 3 | import io.usethesource.impulse.services.IAutoEditStrategy; 4 | import org.eclipse.jface.text.BadLocationException; 5 | import org.eclipse.jface.text.DocumentCommand; 6 | import org.eclipse.jface.text.IDocument; 7 | import org.eclipse.jface.text.IRegion; 8 | import org.eclipse.jface.text.TextUtilities; 9 | 10 | import frege.FregePlugin; 11 | import frege.imp.preferences.FregePreferencesConstants; 12 | 13 | public class AutoEditStrategy implements IAutoEditStrategy { 14 | int tabWidth = FregePlugin.getInstance().getPreferencesService(). 15 | getIntPreference(FregePreferencesConstants.P_TABWITH); 16 | // private static java.util.regex.Pattern spaces = java.util.regex.Pattern.compile("^(\\s+)"); 17 | public void customizeDocumentCommand(IDocument doc, DocumentCommand cmd) { 18 | if (cmd.doit == false) 19 | return; 20 | // START_HERE 21 | try { 22 | if (cmd.length == 0 && cmd.text != null 23 | && isLineDelimiter(doc, cmd.text)) { 24 | smartIndentAfterNewline(doc, cmd); 25 | 26 | } 27 | else if (cmd.length == 1 && 28 | (cmd.text == null || cmd.text.length() == 0)) { 29 | 30 | // backspace 31 | smartIndentOnKeypress(doc, cmd); 32 | } 33 | // else if (cmd.length == 0 && cmd.text != null 34 | // && cmd.text.length()==1) { 35 | // if (cmd.text.equals("(")) cmd.text = "()"; 36 | // else if (cmd.text.equals("{")) cmd.text = "{}"; 37 | // else if (cmd.text.equals("[")) cmd.text = "[]"; 38 | // } 39 | } catch (BadLocationException e) { 40 | System.err.println(this.getClass().getName() + e.getMessage()); 41 | return; 42 | } 43 | } 44 | 45 | /** 46 | * Put as much spaces on the start of the next line as there are on the current line 47 | * 48 | * @param doc 49 | * @param cmd 50 | * @throws BadLocationException 51 | */ 52 | private void smartIndentAfterNewline(IDocument doc, DocumentCommand cmd) throws BadLocationException { 53 | 54 | IRegion thisLine = doc.getLineInformationOfOffset(cmd.offset); 55 | String text = doc.get(thisLine.getOffset(), thisLine.getLength()); 56 | int i = 0; 57 | for (i = 0; i < text.length() 58 | && Character.isSpaceChar(text.charAt(i)); i++); 59 | // indent only if this was not all space 60 | if (i+1 != text.length()) 61 | cmd.text += text.substring(0, i); 62 | } 63 | 64 | /** 65 | * If this is deletion of a character, it deletes all characters till 66 | * the previous tab stop if all of those characters are spaces. 67 | * @param doc the document 68 | * @param cmd the command 69 | * @throws BadLocationException 70 | */ 71 | private void smartIndentOnKeypress(IDocument doc, DocumentCommand cmd) throws BadLocationException { 72 | // System.err.println("smartIndentOnKeypress: offset=" + cmd.offset 73 | // + ", length=" + cmd.length 74 | // + ", text='" + cmd.text 75 | // + "', caret=" + cmd.caretOffset); 76 | IRegion line = doc.getLineInformationOfOffset(cmd.offset); 77 | String text = doc.get(line.getOffset(), line.getLength()); 78 | int offsetInLine = cmd.offset - line.getOffset(); 79 | // char charAtOffset = text.charAt(offsetInLine); 80 | 81 | int tab = offsetInLine; 82 | while (tabWidth > 0 && tab % tabWidth != 0) tab--; 83 | // System.err.println("smartIndentOnKeypress: offset=" + offsetInLine 84 | // + ", tab=" + tab 85 | // + ", char='" + charAtOffset + "'"); 86 | boolean allSpaces = true; 87 | for (int i=tab; i <= offsetInLine; i++) 88 | allSpaces = allSpaces && i < text.length() && Character.isWhitespace(text.charAt(i)); 89 | if (allSpaces) { 90 | cmd.offset = line.getOffset() + tab; 91 | cmd.length = offsetInLine - tab + 1; 92 | } 93 | } 94 | 95 | private boolean isLineDelimiter(IDocument doc, String text) { 96 | String[] delimiters = doc.getLegalLineDelimiters(); 97 | if (delimiters != null) { 98 | return TextUtilities.equals(delimiters, text) > -1; 99 | } 100 | return false; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/frege/imp/actions/EnableFregeNature.java: -------------------------------------------------------------------------------- 1 | package frege.imp.actions; 2 | 3 | 4 | import org.eclipse.core.resources.IProject; 5 | import org.eclipse.core.runtime.CoreException; 6 | import org.eclipse.core.runtime.IPath; 7 | import org.eclipse.core.runtime.Path; 8 | import org.eclipse.jdt.core.IClasspathEntry; 9 | import org.eclipse.jdt.core.IJavaProject; 10 | import org.eclipse.jdt.core.JavaCore; 11 | import org.eclipse.jdt.core.JavaModelException; 12 | import org.eclipse.jface.action.IAction; 13 | import org.eclipse.jface.viewers.ISelection; 14 | import org.eclipse.jface.viewers.IStructuredSelection; 15 | import org.eclipse.ui.IWorkbenchWindow; 16 | import org.eclipse.ui.IWorkbenchWindowActionDelegate; 17 | 18 | import frege.FregePlugin; 19 | import frege.imp.builders.FregeNature; 20 | 21 | public class EnableFregeNature implements IWorkbenchWindowActionDelegate { 22 | private IProject fProject; 23 | 24 | public EnableFregeNature() { 25 | } 26 | 27 | public void dispose() { 28 | } 29 | 30 | public void init(IWorkbenchWindow window) { 31 | } 32 | 33 | public void run(IAction action) { 34 | boolean isJava = false; 35 | new FregeNature().addToProject(fProject); 36 | try { 37 | isJava = fProject.hasNature("org.eclipse.jdt.core.javanature"); 38 | 39 | } catch (CoreException e) { 40 | // remain silent in actions 41 | } 42 | 43 | if (isJava) { 44 | IJavaProject jp = JavaCore.create(fProject); 45 | try { 46 | IClasspathEntry[] old = jp.getRawClasspath(); 47 | IClasspathEntry[] cpe = new IClasspathEntry[old.length+1]; 48 | int i = 0; 49 | for (i=0; i getDeps(String content, String fromPath) { 85 | TGlobal global = frege.prelude.PreludeBase.TST 86 | .performUnsafe(CompilerOptions.eclipseOptions.call()) 87 | .call(); 88 | 89 | // set source file into global (why?) 90 | global = TGlobal.upd$options(global, TOptions.upd$source( 91 | TGlobal.options(global), 92 | fromPath)); 93 | 94 | return FregeParseController.funSTG( 95 | Utilities.getDependencies(content), 96 | global); 97 | } 98 | /** 99 | * Collects compilation-unit dependencies for the given file, and records 100 | * them via calls to fDependency.addDependency(). 101 | */ 102 | @Override public void collectDependencies(IFile file) { 103 | 104 | try { 105 | final ISourceProject sourceProject 106 | = ModelFactory.open(file.getProject()); 107 | final String fromPath = file.getFullPath().toString(); 108 | final FregeParseController.FregeData fd 109 | = new FregeParseController.FregeData(sourceProject); 110 | final String[] srcs = fd.getSp().split(System.getProperty("path.separator")); 111 | final String contents = BuilderUtils.getFileContents(file); 112 | 113 | getPlugin().writeInfoMsg( 114 | "Collecting dependencies from frege file: " + fromPath); 115 | TList packs = getDeps(contents, fromPath); 116 | // packs = Utilities.correctDependenciesFor(packs, fromPath); 117 | 118 | while (true) { 119 | final DCons cons = packs.asCons(); 120 | if (cons == null) break; 121 | packs = cons.mem2.call(); 122 | final String pack = cons.mem1.call(); 123 | final IFile known = fPackages.get(pack); 124 | if (known != null) { 125 | this.addDependency(file, known); 126 | continue; 127 | } 128 | final String fr = pack.replaceAll("\\.", "/") + ".fr"; 129 | for (String sf: srcs) { 130 | final IPath p = new Path(sf + "/" + fr); 131 | // getProject().getWorkspace().getRoot().getFile(new Path(depPath)); 132 | final IResource toRes = file.getProject().findMember(p); 133 | getPlugin().writeInfoMsg( 134 | "DependenciesCollector looks for: " + p.toPortableString()); 135 | if (toRes != null && toRes instanceof IFile) { 136 | final IFile to = (IFile) toRes; 137 | // avoid endless recursion for frege.prelude.Base -> frege.prelude.Base 138 | if (!file.equals(to)) { 139 | this.fPackages.put(pack, to); 140 | this.addDependency(file, to); 141 | getPlugin().writeInfoMsg( 142 | "DependenciesCollector found: " + to.getFullPath()); 143 | } 144 | break; 145 | } 146 | } 147 | } 148 | } 149 | catch (ModelException mex) { 150 | getPlugin().writeErrorMsg( 151 | "Can't get source project: " + mex.getMessage()); 152 | return; 153 | } 154 | } 155 | 156 | 157 | 158 | /** 159 | * Compile one frege file. 160 | */ 161 | @Override public boolean compiled(final IFile file, IProgressMonitor monitor) { 162 | boolean succ = false; 163 | if (monitor.isCanceled()) return false; 164 | try { 165 | getPlugin().writeInfoMsg("Building frege file: " + file.getName()); 166 | succ = runParserForCompiler(file, monitor); 167 | // do wee need that? 168 | // doRefresh(file.getProject()); 169 | } catch (Exception e) { 170 | // catch Exception, because any exception could break the 171 | // builder infrastructure. 172 | getPlugin().logException(e.getMessage(), e); 173 | } 174 | return succ; 175 | } 176 | @Override public void compile(IFile f, IProgressMonitor m) { compiled(f, m); } 177 | 178 | 179 | /** 180 | * This is a compiler implementation that simply uses the parse controller 181 | * to parse the given file, adding markers to the file for any errors, 182 | * warnings or hints that are reported. 183 | * 184 | * Error markers are created by a special type of message handler (i.e., implementation 185 | * of IMessageHandler) known as a MarkerCreator. The MarkerCreator is passed to the 186 | * parse controller. The parser reports its error messages to the MarkerCreator, and 187 | * the MarkerCreator puts corresponding error markers on the file. 188 | * 189 | * 190 | * @param file input source file 191 | * @param monitor progress monitor 192 | */ 193 | protected boolean runParserForCompiler(final IFile file, 194 | final IProgressMonitor monitor) { 195 | // a class we can give the compiler as progress monitor 196 | class CompProgress extends org.eclipse.jdt.core.compiler.CompilationProgress implements IProgressMonitor { 197 | 198 | @Override 199 | public void begin(int arg0) { } 200 | 201 | @Override 202 | public void done() { } 203 | 204 | @Override 205 | public boolean isCanceled() { 206 | return monitor.isCanceled(); 207 | } 208 | 209 | @Override 210 | public void setTaskName(String arg0) {} 211 | 212 | @Override 213 | public void worked(int arg0, int arg1) { } 214 | 215 | @Override 216 | public void beginTask(String name, int totalWork) { 217 | 218 | } 219 | 220 | @Override 221 | public void internalWorked(double work) { 222 | monitor.internalWorked(work); 223 | } 224 | 225 | @Override 226 | public void setCanceled(boolean value) { 227 | monitor.setCanceled(value); 228 | } 229 | 230 | @Override 231 | public void subTask(String name) { 232 | monitor.subTask(name); 233 | } 234 | 235 | @Override 236 | public void worked(int work) { 237 | } 238 | 239 | } 240 | 241 | boolean success = false; 242 | try { 243 | FregeParseController parseController = new FregeParseController(); 244 | 245 | MarkerCreatorWithBatching markerCreator = new MarkerCreatorWithBatching(file, parseController, this); 246 | 247 | parseController.getAnnotationTypeInfo().addProblemMarkerType( 248 | getErrorMarkerID()); 249 | 250 | ISourceProject sourceProject = ModelFactory.open(file.getProject()); 251 | parseController.initialize(file.getProjectRelativePath(), 252 | sourceProject, markerCreator); 253 | 254 | String contents = BuilderUtils.getFileContents(file); 255 | final TGlobal result = parseController.parse(contents, new CompProgress()); 256 | if (FregeParseController.errors(result) == 0) { 257 | // run the eclipse java compiler 258 | final String target = Main.targetPath(result, ".java"); 259 | 260 | getPlugin().writeInfoMsg("built: " + target); 261 | // get the frege path and build path 262 | final String bp = TOptions.dir( TGlobal.options(result) ); 263 | final TList ourPath = CompilerOptions.ourPath(TGlobal.options(result)); 264 | final String fp = PreludeText.joined( 265 | Thunk.lazy(System.getProperty("path.separator")), 266 | ourPath 267 | ).call(); 268 | final TList srcPath = TOptions.sourcePath(TGlobal.options(result)); 269 | final String sp = PreludeText.joined( 270 | Thunk.lazy(System.getProperty("path.separator")), 271 | srcPath 272 | ).call(); 273 | // construct the commandline 274 | final String cmdline = "-cp " + "\"" + fp + "\"" 275 | + " -d " + "\"" + bp + "\"" 276 | + " -sourcepath " + "\"" + sp + "\"" 277 | + " -Xemacs -1.8 -encoding UTF-8 " 278 | + "\"" + target + "\""; 279 | getPlugin().writeInfoMsg("batch-compile " + cmdline); 280 | final StringWriter errs = new StringWriter(); 281 | success = org.eclipse.jdt.core.compiler.batch.BatchCompiler.compile( 282 | cmdline, 283 | new PrintWriter(System.out), 284 | new PrintWriter(errs), 285 | new CompProgress()); 286 | 287 | /* write java error messages to some file. 288 | if (errs.toString().length() > 0) try { 289 | FileWriter f = new FileWriter(target + ".errors"); 290 | f.append(errs.toString()); 291 | f.close(); 292 | } 293 | catch (IOException e) { 294 | getPlugin().writeErrorMsg("could not write java compiler errors " + e.getMessage()); 295 | } 296 | */ 297 | 298 | if (!success) { 299 | TPosition pos = Global.packageStart(result).call(); 300 | TToken module = TPosition.first(pos); 301 | int line = TToken.line(module); 302 | int chStart = TToken.offset(module); 303 | int chEnd = chStart + TToken.length(module); 304 | String msg = errs.toString(); 305 | String[] msgs = msg.split(System.getProperty("line.terminator", "\n")); 306 | Pattern p = Pattern.compile(":\\d+:\\s+error:(.*)"); 307 | for (String s : msgs) { 308 | if (s == null) continue; 309 | // getPlugin().writeInfoMsg(s); 310 | Matcher m = p.matcher(s); 311 | if (m.find()) { 312 | String se = m.group(1); 313 | markerCreator.addMarker( 314 | IMarker.SEVERITY_ERROR, 315 | se, line, chStart, chEnd); 316 | } 317 | } 318 | getPlugin().writeErrorMsg("java compiler failed on " + target); 319 | markerCreator.addMarker(IMarker.SEVERITY_INFO, 320 | "Java compiler errors are almost always caused by bad native declarations. " 321 | + "When you're sure this is out of the question you've found a compiler bug, " 322 | + "please report under https://github.com/frege/frege/issues and attach a copy of " 323 | + target, 324 | line, chStart, chEnd); 325 | } 326 | else { 327 | // notify that we have a new module 328 | parseController.justCompiled(); 329 | } 330 | } 331 | 332 | if (markerCreator instanceof MarkerCreatorWithBatching) { 333 | ((MarkerCreatorWithBatching) markerCreator).flush(monitor); 334 | } 335 | } catch (ModelException e) { 336 | getPlugin().logException( 337 | "Example builder returns without parsing due to a ModelException", 338 | e); 339 | } catch (LimitExceededException e) { 340 | getPlugin().logException( 341 | "Caught exception while building: ", 342 | e); 343 | } 344 | return success; 345 | } 346 | 347 | /** 348 | * Always false, there is not such thing in Frege 349 | */ 350 | @Override 351 | protected boolean isNonRootSourceFile(IFile file) { 352 | return false; 353 | } 354 | 355 | } 356 | -------------------------------------------------------------------------------- /src/frege/imp/builders/FregeBuilderBase.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * This is a rewrite of io.usethesource.impulse.builder.BuilderBase 4 | * with clutter removed not needed for Frege and a dependency 5 | * management that fits our needs. 6 | * 7 | * The Frege Builder assumes that every Frege Project is a 8 | * Java Project and that dependencies between Frege sources 9 | * are non-cyclic. The latter is guaranteed by the language. 10 | * 11 | * We nevertheless must extend BuilderBase so that we can create MarkerCreatorWithBatching. 12 | * This is a design flaw in the IMP framework. 13 | */ 14 | 15 | package frege.imp.builders; 16 | 17 | import java.util.Collection; 18 | import java.util.HashMap; 19 | import java.util.HashSet; 20 | import java.util.LinkedList; 21 | import java.util.List; 22 | import java.util.Map; 23 | import java.util.Set; 24 | 25 | import org.eclipse.core.resources.IFile; 26 | import org.eclipse.core.resources.IProject; 27 | import org.eclipse.core.resources.IResource; 28 | import org.eclipse.core.resources.IResourceDelta; 29 | import org.eclipse.core.resources.IResourceDeltaVisitor; 30 | import org.eclipse.core.resources.IResourceVisitor; 31 | import org.eclipse.core.runtime.CoreException; 32 | import org.eclipse.core.runtime.IPath; 33 | import org.eclipse.core.runtime.IProgressMonitor; 34 | import org.eclipse.core.runtime.IStatus; 35 | import org.eclipse.core.runtime.Status; 36 | import io.usethesource.impulse.builder.BuilderBase; 37 | import io.usethesource.impulse.language.Language; 38 | import io.usethesource.impulse.language.LanguageRegistry; 39 | import io.usethesource.impulse.preferences.IPreferencesService; 40 | import org.eclipse.jdt.core.IJavaProject; 41 | import org.eclipse.jdt.core.JavaCore; 42 | import org.eclipse.jdt.core.JavaModelException; 43 | import frege.FregePlugin; 44 | 45 | 46 | public abstract class FregeBuilderBase extends BuilderBase { 47 | 48 | public FregeBuilderBase() {} 49 | 50 | public static final String LANGUAGE_NAME = FregePlugin.kLanguageID; 51 | 52 | public static final Language LANGUAGE = LanguageRegistry 53 | .findLanguage(LANGUAGE_NAME); 54 | 55 | 56 | public final IResourceVisitor fResourceVisitor= new SourceCollectorVisitor(); 57 | 58 | protected final IResourceDeltaVisitor fDeltaVisitor= new SourceDeltaVisitor(); 59 | 60 | protected IPreferencesService fPrefService; 61 | 62 | public final Set fChangedSources= new HashSet(); 63 | 64 | // protected final Set fSourcesToCompile= new HashSet(); 65 | // protected final Set fSourcesForDeps= new HashSet(); 66 | 67 | protected Map> fDependencies = new HashMap>(); 68 | protected Map fPackages = new HashMap(); 69 | final protected String fDependencyInfo = "not here"; // make base class item invisible 70 | 71 | protected boolean buildStatus = false; 72 | 73 | /** 74 | * Decide whether a file needs to be build using this builder. 75 | * 76 | * @return true if file has extension .fr and does not live below the output path. 77 | */ 78 | @Override public boolean isSourceFile(IFile file) { 79 | final IPath path = file.getFullPath(); 80 | if (path == null) 81 | return false; 82 | final IProject rp = file.getProject(); 83 | final IJavaProject jp = rp != null ? JavaCore.create(rp) : null; 84 | try { 85 | if (jp != null) { 86 | final IPath bin = jp.getOutputLocation(); 87 | if (bin != null) { 88 | final IPath rbin = bin.makeRelativeTo(rp.getFullPath()); 89 | final IPath src = path.makeRelativeTo(rp.getFullPath()); 90 | return src != null && rbin != null 91 | && !rbin.isPrefixOf(src) && LANGUAGE.hasExtension(path.getFileExtension()); 92 | } 93 | } 94 | } 95 | catch (JavaModelException e) { 96 | return false; 97 | } 98 | return false; 99 | } 100 | 101 | /** 102 | * @return true if this resource identifies the output folder 103 | */ 104 | @Override public boolean isOutputFolder(IResource resource) { 105 | final IPath path = resource.getFullPath(); 106 | if (path == null) 107 | return false; 108 | final IProject rp = resource.getProject(); 109 | final IJavaProject jp = rp != null ? JavaCore.create(rp) : null; 110 | try { 111 | if (jp != null) { 112 | final IPath bin = jp.getOutputLocation(); 113 | if (bin != null) { 114 | final IPath rbin = bin.makeRelativeTo(rp.getFullPath()); 115 | final IPath res = path.makeRelativeTo(rp.getFullPath()); 116 | return res != null && rbin != null && rbin.equals(res); 117 | } 118 | } 119 | } 120 | catch (JavaModelException e) { 121 | return false; 122 | } 123 | return false; 124 | } 125 | 126 | 127 | private final class SourceDeltaVisitor implements IResourceDeltaVisitor { 128 | @Override 129 | public boolean visit(IResourceDelta delta) throws CoreException { 130 | return processResource(delta.getResource()); 131 | } 132 | } 133 | 134 | private class SourceCollectorVisitor implements IResourceVisitor { 135 | @Override 136 | public boolean visit(IResource res) throws CoreException { 137 | return processResource(res); 138 | } 139 | } 140 | 141 | private boolean processResource(IResource resource) { 142 | if (resource instanceof IFile) { 143 | IFile file= (IFile) resource; 144 | 145 | if (file.exists()) { 146 | if (isSourceFile(file) || isNonRootSourceFile(file)) { 147 | fChangedSources.add(file); 148 | } 149 | } 150 | return false; 151 | } else if (isOutputFolder(resource)) { 152 | return false; 153 | } 154 | return true; 155 | } 156 | 157 | private class AllSourcesVisitor implements IResourceVisitor { 158 | private final Collection fResult; 159 | 160 | public AllSourcesVisitor(Collection result) { 161 | fResult= result; 162 | } 163 | 164 | @Override 165 | public boolean visit(IResource resource) throws CoreException { 166 | if (resource instanceof IFile) { 167 | IFile file= (IFile) resource; 168 | 169 | if (file.exists()) { 170 | if (isSourceFile(file) || isNonRootSourceFile(file)) { 171 | fResult.add(file); 172 | } 173 | } 174 | return false; 175 | } else if (isOutputFolder(resource)) { 176 | return false; 177 | } 178 | return true; 179 | } 180 | } 181 | 182 | 183 | @Override 184 | @SuppressWarnings({ "rawtypes" }) 185 | protected IProject[] build(int kind, Map args, IProgressMonitor monitor) { 186 | if (getPreferencesService().getProject() == null) { 187 | getPreferencesService().setProject(getProject()); 188 | } 189 | 190 | fChangedSources.clear(); 191 | 192 | boolean haveCompleteDeps = false; 193 | List allSources= new LinkedList(); 194 | 195 | if (fDependencies.isEmpty() || kind == FULL_BUILD || kind == CLEAN_BUILD) { 196 | fDependencies.clear(); 197 | fPackages.clear(); 198 | try { 199 | getProject().accept(new AllSourcesVisitor(allSources)); 200 | } catch (CoreException e) { 201 | getPlugin().getLog().log(new Status(IStatus.ERROR, getPlugin().getID(), e.getLocalizedMessage(), e)); 202 | } 203 | // Collect deps now, so we can compile everything necessary in the case where 204 | // we have no dep info yet (e.g. first build for this Eclipse invocation -- 205 | // we don't persist the dep info yet) but we've been asked to do an auto build 206 | // b/c of workspace changes. 207 | collectDependencies(monitor, allSources); 208 | haveCompleteDeps = true; 209 | } 210 | 211 | if (kind == FULL_BUILD || kind == CLEAN_BUILD) { 212 | clearMarkersOn(allSources); 213 | } 214 | 215 | try { 216 | collectSourcesToCompile(monitor); 217 | if (!haveCompleteDeps) 218 | collectDependencies(monitor, fChangedSources); 219 | compileNecessarySources(monitor); 220 | monitor.done(); 221 | } catch (CoreException e) { 222 | getPlugin().writeErrorMsg("Build failed: " + e.getMessage()); 223 | } 224 | return new IProject[0]; 225 | } 226 | 227 | /** 228 | *

Add to list of sources to compile after files this one depends on that are 229 | * also in the list of files to compile.

230 | * @param source the file to add 231 | * @param acc the list of files to compile so far 232 | * @return a new list with maybe some more files added 233 | */ 234 | private List addAfterDeps(IFile source, List acc, Collection toCompile) { 235 | if (acc.contains(source)) return acc; 236 | // compile files this one depends on *before* this one 237 | // This terminates because Frege dependencies form an acyclic graph 238 | 239 | Set thisDeps = fDependencies.get(source); 240 | if (thisDeps == null || thisDeps.isEmpty()) { 241 | getPlugin().writeInfoMsg(source.getName() + " has no dependencies (yet)."); 242 | collectDependencies(source); 243 | thisDeps = fDependencies.get(source); 244 | if (thisDeps == null) { 245 | getPlugin().writeInfoMsg(source.getName() + " has no dependencies at all."); 246 | } 247 | } 248 | if (thisDeps != null) for (IFile depFile : thisDeps) { 249 | // IFile depFile = getProject().getWorkspace().getRoot().getFile(new Path(depPath)); 250 | if (isSourceFile(depFile) && toCompile.contains(depFile)) { 251 | System.err.println("addafterdeps: source=" + source + ", dep=" + depFile); 252 | acc = addAfterDeps(depFile, acc, toCompile); 253 | } 254 | } 255 | acc = new LinkedList(acc); 256 | acc.add(source); 257 | return acc; 258 | } 259 | 260 | /** 261 | * Let it be known to the builder that File from depends on to 262 | * @param from the source file that imports to 263 | * @param to the file that is imported by from 264 | */ 265 | public void addDependency(IFile from, IFile to) { 266 | if (fDependencies.get(from) == null) 267 | fDependencies.put(from, new HashSet()); 268 | if (from.equals(to)) return; 269 | fDependencies.get(from).add(to); 270 | } 271 | 272 | /** 273 | * Checks if a file depends on another one directly or indirectly 274 | * @param a 275 | * @param b 276 | * @return true, if a depends on b, false otherwise 277 | */ 278 | protected boolean usesTransitive(IFile a, IFile b) { 279 | if (a.equals(b)) return false; 280 | final Set deps = new HashSet(); 281 | transDep(a, deps); 282 | return deps.contains(b); 283 | } 284 | 285 | /** 286 | * Determine transitive dependencies 287 | */ 288 | public void transDep(IFile cc, Set ccs) { 289 | if (ccs.contains(cc)) return; // save work 290 | ccs.add(cc); 291 | // add the direct dependencies recursively 292 | Set deps = fDependencies.get(cc); 293 | if (deps != null) 294 | for (IFile k : deps) { 295 | transDep(k, ccs); 296 | } 297 | return; 298 | } 299 | 300 | /** 301 | * Add cc and any known source file that depends on it to ccs 302 | * 303 | * @param cc the file that will be compiled 304 | * @param ccs the accumulated set of files that will be compiled 305 | */ 306 | protected void addTransitive(IFile cc, Set ccs) { 307 | if (ccs.contains(cc)) return; // save duplication of work 308 | ccs.add(cc); 309 | 310 | final Set keys = fDependencies.keySet(); 311 | for (IFile k : keys) { 312 | if (fDependencies.get(k).contains(cc)) addTransitive(k, ccs); 313 | } 314 | } 315 | 316 | /** 317 | * Determines the files to compile and compiles them in the correct order. 318 | * 319 | * All files in fChangedSources must be compiled. 320 | * 321 | * All files that depend on compiled files must be compiled. 322 | * 323 | * Once a compilation fails, other files that depend on the failed one will not be compiled. 324 | */ 325 | @Override 326 | protected void compileNecessarySources(IProgressMonitor monitor) { 327 | Set toCompile = new HashSet(); 328 | for (IFile f : fChangedSources) 329 | addTransitive(f, toCompile); 330 | 331 | String show = ""; 332 | List ord = new LinkedList(); 333 | for(IFile src : toCompile) { 334 | if (!isSourceFile(src)) continue; 335 | if (show.length() > 0) show += ", "; 336 | show += src.getName(); 337 | ord = addAfterDeps(src, ord, toCompile); 338 | } 339 | getPlugin().writeInfoMsg("Files to build: " + show); 340 | 341 | show = ""; 342 | for(IFile src : ord) { 343 | if (!isSourceFile(src)) continue; 344 | if (show.length() > 0) show += ", "; 345 | show += src.getName(); 346 | } 347 | getPlugin().writeInfoMsg("Build order: " + show); 348 | 349 | monitor.beginTask("compiling " + show, ord.size()); 350 | 351 | Set failed = new HashSet(); 352 | 353 | for(IFile srcFile : ord) { 354 | if (monitor.isCanceled()) break; 355 | monitor.subTask("building " + srcFile.getName()); 356 | boolean usesFailed = false; 357 | for (IFile f: failed) { 358 | if (usesTransitive(srcFile, f)) { 359 | usesFailed = true; 360 | break; 361 | } 362 | } 363 | if (!usesFailed) { 364 | clearMarkersOn(srcFile); 365 | if (!compiled(srcFile, monitor)) { 366 | failed.add(srcFile); 367 | } 368 | } 369 | monitor.worked(1); 370 | } 371 | 372 | monitor.done(); 373 | } 374 | 375 | abstract boolean compiled(IFile srcFile, IProgressMonitor monitor); 376 | 377 | protected void collectDependencies(IProgressMonitor monitor, Collection sources) { 378 | for(IFile srcFile: sources) { 379 | collectDependencies(srcFile); 380 | if (monitor.isCanceled()) break; 381 | } 382 | } 383 | 384 | 385 | /** 386 | * Visits the project delta, if any, or the entire project, and determines the set 387 | * of files that need recompilation, and adds them to fChangedSources. 388 | * @param monitor 389 | * @throws CoreException 390 | */ 391 | private void collectSourcesToCompile(IProgressMonitor monitor) throws CoreException { 392 | IResourceDelta delta= getDelta(getProject()); 393 | // boolean emitDiags= getDiagPreference(); 394 | 395 | if (delta != null) { 396 | delta.accept(fDeltaVisitor); 397 | for (IFile chg : fChangedSources) { 398 | fDependencies.put(chg, new HashSet()); // clear dependencies of changed files 399 | } 400 | collectDependencies(monitor, fChangedSources); // re-collect dependencies of changed files 401 | } else { 402 | getProject().accept(fResourceVisitor); 403 | } 404 | } 405 | 406 | } 407 | -------------------------------------------------------------------------------- /src/frege/imp/builders/FregeNature.java: -------------------------------------------------------------------------------- 1 | package frege.imp.builders; 2 | 3 | import io.usethesource.impulse.builder.ProjectNatureBase; 4 | import io.usethesource.impulse.runtime.IPluginLog; 5 | 6 | import frege.FregePlugin; 7 | 8 | public class FregeNature extends ProjectNatureBase { 9 | public FregeNature() { super(); } 10 | public static final String k_natureID = FregePlugin.kPluginID 11 | + ".frege.nature"; 12 | 13 | public String getNatureID() { 14 | return k_natureID; 15 | } 16 | 17 | public String getBuilderID() { 18 | return FregeBuilder.BUILDER_ID; 19 | } 20 | 21 | public void refreshPrefs() { 22 | // TODO implement preferences and hook in here 23 | } 24 | 25 | public IPluginLog getLog() { 26 | return FregePlugin.getInstance(); 27 | } 28 | 29 | public String getDownstreamBuilderID() { 30 | // There is no builder that will consume artifacts created by this nature's builder, 31 | // hence null 32 | return null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/frege/imp/contentProposer/ContentProposer.java: -------------------------------------------------------------------------------- 1 | package frege.imp.contentProposer; 2 | 3 | import frege.compiler.types.Tokens.TToken; 4 | import frege.compiler.types.Global.TGlobal; 5 | import frege.compiler.types.Global.TSubSt; 6 | import frege.ide.Utilities; 7 | import frege.ide.Utilities.IShow_Proposal; 8 | import frege.ide.Utilities.TProposal; 9 | import frege.compiler.enums.TokenID; 10 | import frege.imp.parser.*; 11 | import frege.prelude.PreludeBase.TList; 12 | import frege.run8.Thunk; 13 | import frege.run8.Func; 14 | import frege.runtime.Phantom.RealWorld; 15 | 16 | import java.util.*; 17 | 18 | import org.eclipse.jface.text.ITextViewer; 19 | import org.eclipse.jface.text.Region; 20 | import org.eclipse.jface.text.contentassist.ICompletionProposal; 21 | 22 | import io.usethesource.impulse.services.IContentProposer; 23 | import io.usethesource.impulse.editor.ErrorProposal; 24 | import io.usethesource.impulse.editor.SourceProposal; 25 | import io.usethesource.impulse.parser.IParseController; 26 | 27 | 28 | public class ContentProposer implements IContentProposer { 29 | /** 30 | * An extension of {@link SourceProposal} that computes additional information 31 | * lazily. 32 | */ 33 | static class Proposal extends SourceProposal { 34 | Func.U additional; // IO String! 35 | String info; 36 | public Proposal(String proposal, String newText, String prefix, int offset, int length, 37 | int cursor, Func.U additional) { 38 | super(proposal, newText, prefix, new Region(offset, length), cursor); 39 | this.additional = additional; 40 | info = null; 41 | } 42 | 43 | public String getAdditionalProposalInfo() { 44 | if (info == null) { 45 | info = additional.apply(Thunk.lazyWorld).call(); 46 | } 47 | return info; 48 | } 49 | 50 | public static Proposal convert(final TProposal p) { 51 | final String newT = TProposal.newText(p); 52 | final int off = TProposal.off(p); 53 | return new Proposal( 54 | TProposal.proposal(p), 55 | newT, 56 | "", // TProposal.prefix(p), 57 | off, 58 | TProposal.len(p), 59 | TProposal.cursor(p)+off+newT.length(), 60 | p.mem$additional.call() 61 | ); 62 | } 63 | } 64 | 65 | 66 | /** 67 | * Returns an array of content proposals applicable relative to the AST of the given 68 | * parse controller at the given position. 69 | * 70 | * (The provided ITextViewer is not used in the default implementation provided here 71 | * but but is stipulated by the IContentProposer interface for purposes such as accessing 72 | * the IDocument for which content proposals are sought.) 73 | * 74 | * @param controller A parse controller from which the AST of the document being edited 75 | * can be obtained 76 | * @param int The offset for which content proposals are sought 77 | * @param viewer The viewer in which the document represented by the AST in the given 78 | * parse controller is being displayed (may be null for some implementations) 79 | * @return An array of completion proposals applicable relative to the AST of the given 80 | * parse controller at the given position 81 | */ 82 | public ICompletionProposal[] getContentProposals(IParseController ctlr, 83 | int offset, ITextViewer viewer) { 84 | FregeParseController parser = (FregeParseController) ctlr; 85 | 86 | 87 | // SourceViewer srcViewer = viewer instanceof SourceViewer ? (SourceViewer) viewer : null ; 88 | // if (srcViewer != null) { 89 | // ContentAssistantFacade facade = srcViewer.getContentAssistantFacade(); 90 | // if (facade != null) { 91 | // facade.getHandler(ContentAssistant.SELECT_NEXT_PROPOSAL_COMMAND_ID); 92 | // } 93 | // } 94 | // String src = viewer.getDocument().get(); 95 | // UniversalEditor editor = (UniversalEditor) viewer; 96 | // editor.getDocumentProvider(); 97 | // 98 | // if (src.length() != parser.getLeng() 99 | // || src.hashCode() != parser.getHash()) { 100 | // return result.toArray(new ICompletionProposal[result.size()]); // buffer dirty, return previous result 101 | // } 102 | 103 | List result = new ArrayList(); 104 | final TGlobal g = parser.getGoodAst(); 105 | final TToken[] tokens = TSubSt.toks(TGlobal.sub(g)); 106 | 107 | if (g != null) { 108 | int inx = FregeSourcePositionLocator.previous(tokens, offset); 109 | 110 | TToken token = FregeSourcePositionLocator.tokenAt(tokens, inx); 111 | TToken tprev = FregeSourcePositionLocator.tokenAt(tokens, inx-1); 112 | boolean direct = false; 113 | boolean inside = false; 114 | String id = "none"; 115 | String idprev = tprev == null ? "" 116 | : TokenID.IShow_TokenID.show(TToken.tokid(tprev)) + ","; 117 | String pref = ""; 118 | String val = null; 119 | if (token != null) { 120 | direct = TToken.offset(token) + TToken.length(token) == offset; 121 | inside = TToken.offset(token) + TToken.length(token) > offset; 122 | id = TokenID.IShow_TokenID.show(TToken.tokid(token)); 123 | val = TToken.value(token); 124 | try { 125 | pref = inside ? val.substring(0, offset - TToken.offset(token)) 126 | : (direct ? val : ""); 127 | } catch (IndexOutOfBoundsException e) { 128 | // stay on the safe side 129 | pref = ""; 130 | } 131 | } 132 | System.err.println("getContentProposal offset=" + offset 133 | + ", tokenID=" + idprev + id 134 | + ", value=\"" + val + '"' 135 | + ", direct=" + direct 136 | + ", inside=" + inside); 137 | 138 | TList ps = null; 139 | boolean first = true; 140 | /* 141 | if (token != null && (TToken.tokid(token) == TTokenID.IMPORT 142 | || TToken.tokid(tprev) == TTokenID.IMPORT)) { 143 | pref = token != null && TToken.tokid(token) != TTokenID.IMPORT 144 | ? TToken.value(token) 145 | : ""; 146 | 147 | List packs = parser.getFD().getAllSources(pref); 148 | for (String p: packs) { 149 | result.add(new SourceProposal(p, pref, offset)); 150 | } 151 | first = result.size() == 0; 152 | } 153 | else */ { 154 | ps = Utilities.proposeContent(g, parser.ourRoot(), offset, tokens, inx); 155 | while (true) { 156 | final TList.DCons node = ps.asCons(); 157 | if (node == null) break; 158 | TProposal p = node.mem1.call(); 159 | if (first) { 160 | first = false; 161 | pref = TProposal.prefix(p); 162 | System.err.println("getContentProposal: " + IShow_Proposal.show(p)); 163 | } 164 | result.add(Proposal.convert(p)); 165 | ps = node.mem2.call(); 166 | } 167 | } 168 | 169 | if (first) { // empty proposal list 170 | if (TGlobal.errors(g) > 0) { 171 | result.add(new ErrorProposal( 172 | "No proposals available, please correct syntax errors first.", offset)); 173 | } 174 | else if (pref.length() > 0) { 175 | result.add(new ErrorProposal( 176 | "No proposals available, maybe prefix \"" + pref + "\" too restrictive?", offset)); 177 | } 178 | else { 179 | result.add(new ErrorProposal( 180 | "Can't help you here. Sorry.", offset)); 181 | } 182 | } 183 | } else { 184 | result.add(new ErrorProposal( 185 | "No proposals available - syntax errors", offset)); 186 | } 187 | return result.toArray(new ICompletionProposal[result.size()]); 188 | } 189 | 190 | } 191 | -------------------------------------------------------------------------------- /src/frege/imp/documentation/FregeDocumentationProvider.java: -------------------------------------------------------------------------------- 1 | package frege.imp.documentation; 2 | 3 | import io.usethesource.impulse.parser.IParseController; 4 | import io.usethesource.impulse.services.IDocumentationProvider; 5 | 6 | import frege.ide.Utilities; 7 | import frege.compiler.types.Tokens; 8 | import frege.imp.referenceResolvers.FregeReferenceResolver; 9 | import frege.imp.parser.FregeParseController; 10 | 11 | public class FregeDocumentationProvider implements IDocumentationProvider { 12 | public String getDocumentation(Object entity, IParseController ctlr) { 13 | if (entity == null) 14 | return null; 15 | 16 | if (entity instanceof FregeReferenceResolver.Symbol 17 | || entity instanceof FregeReferenceResolver.Namespace) { 18 | final String s = entity.toString(); 19 | // System.err.println("MARKUP: " + s); 20 | return s; 21 | } 22 | if (entity instanceof Tokens.TToken) { 23 | final Tokens.TToken token = (Tokens.TToken) entity; 24 | final FregeParseController fp = (FregeParseController) ctlr; // what else? 25 | final String s = (String) FregeParseController.funSTIO(Utilities.tokenDocumentation(token), fp.getCurrentAst()); 26 | return (s.length() > 0 ? s : null); 27 | } 28 | // System.err.println("getDocumentation(" + entity.toString() + ")"); 29 | return null; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/frege/imp/editorActions/FregeEditorActionContributions.java: -------------------------------------------------------------------------------- 1 | package frege.imp.editorActions; 2 | 3 | import org.eclipse.core.resources.IFile; 4 | import org.eclipse.core.resources.IWorkspace; 5 | import org.eclipse.core.resources.ResourcesPlugin; 6 | import org.eclipse.core.runtime.IPath; 7 | import org.eclipse.core.runtime.IProgressMonitor; 8 | import org.eclipse.core.runtime.IStatus; 9 | import org.eclipse.core.runtime.Status; 10 | import org.eclipse.core.runtime.jobs.Job; 11 | import io.usethesource.impulse.editor.UniversalEditor; 12 | import io.usethesource.impulse.model.ISourceProject; 13 | import io.usethesource.impulse.parser.IParseController; 14 | import io.usethesource.impulse.services.ILanguageActionsContributor; 15 | import org.eclipse.jface.action.Action; 16 | import org.eclipse.jface.action.IMenuManager; 17 | import org.eclipse.jface.action.IStatusLineManager; 18 | import org.eclipse.jface.action.IToolBarManager; 19 | import org.eclipse.jface.action.MenuManager; 20 | import org.eclipse.jface.text.BadLocationException; 21 | import org.eclipse.jface.text.IDocument; 22 | import org.eclipse.swt.graphics.Point; 23 | import org.eclipse.ui.IEditorPart; 24 | import org.eclipse.ui.PlatformUI; 25 | 26 | import frege.compiler.types.Global.TGlobal; 27 | import frege.imp.builders.FregeBuilder; 28 | import frege.imp.parser.FregeParseController; 29 | // import org.eclipse.ui.IFileEditorInput; 30 | 31 | public class FregeEditorActionContributions implements 32 | ILanguageActionsContributor { 33 | 34 | 35 | private Action fgAction(final UniversalEditor uditor) { 36 | Action it = new Action("f • g") { 37 | public void run() { 38 | UniversalEditor editor = uditor; 39 | if (editor == null) { 40 | IEditorPart ed = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); 41 | if (ed == null) return; 42 | if (ed instanceof UniversalEditor) 43 | editor = (UniversalEditor) ed; 44 | else return; 45 | } 46 | // editor is not null 47 | try { 48 | if (!editor.isEditable()) return; 49 | final Point where = editor.getSelection(); 50 | // System.err.println("we are at " + where); 51 | final IDocument document= editor. 52 | getDocumentProvider(). 53 | getDocument(editor.getEditorInput()); 54 | if (document != null) { 55 | document.replace(where.x, where.y, "•"); 56 | editor.selectAndReveal(where.x+1, 0); 57 | } 58 | } 59 | catch (BadLocationException e) { 60 | // TODO Auto-generated catch block 61 | // e.printStackTrace(); 62 | } 63 | } 64 | }; 65 | it.setDescription("Insert the • symbol for the function composition operator."); 66 | it.setToolTipText(it.getDescription()); 67 | it.setId("frege-editoraction-bullet"); 68 | return it; 69 | } 70 | 71 | private Action rgxAction(final UniversalEditor uditor) { 72 | Action it = new Action("´regex´") { 73 | public void run() { 74 | UniversalEditor editor = uditor; 75 | if (editor == null) { 76 | IEditorPart ed = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); 77 | if (ed == null) return; 78 | // System.err.println(ed.getClass().getName()); 79 | if (ed instanceof UniversalEditor) 80 | editor = (UniversalEditor) ed; 81 | else return; 82 | } 83 | // editor is not null 84 | try { 85 | if (!editor.isEditable()) return; 86 | final Point where = editor.getSelection(); 87 | // System.err.println("we are at " + where); 88 | final IDocument document= editor. 89 | getDocumentProvider(). 90 | getDocument(editor.getEditorInput()); 91 | if (document != null) { 92 | String w = document.get(where.x, where.y); 93 | document.replace(where.x, where.y, "´" + w + "´"); 94 | if (w.length() == 0) 95 | editor.selectAndReveal(where.x+1, 0); 96 | } 97 | } 98 | catch (BadLocationException e) { 99 | // TODO Auto-generated catch block 100 | // e.printStackTrace(); 101 | } 102 | } 103 | }; 104 | it.setDescription("Enclose the selected text in grave accent marks to form a regular expression."); 105 | it.setToolTipText(it.getDescription()); 106 | it.setId("frege-editoraction-rgx"); 107 | return it; 108 | } 109 | 110 | private Action opAction(final UniversalEditor uditor) { 111 | Action it = new Action("`op`") { 112 | public void run() { 113 | UniversalEditor editor = uditor; 114 | if (editor == null) { 115 | IEditorPart ed = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); 116 | if (ed == null) return; 117 | // System.err.println(ed.getClass().getName()); 118 | if (ed instanceof UniversalEditor) 119 | editor = (UniversalEditor) ed; 120 | else return; 121 | } 122 | // editor is not null 123 | try { 124 | if (!editor.isEditable()) return; 125 | final Point where = editor.getSelection(); 126 | // System.err.println("we are at " + where); 127 | final IDocument document= editor. 128 | getDocumentProvider(). 129 | getDocument(editor.getEditorInput()); 130 | if (document != null) { 131 | String w = document.get(where.x, where.y); 132 | document.replace(where.x, where.y, "`" + w + "`"); 133 | if (w.length() == 0) 134 | editor.selectAndReveal(where.x+1, 0); 135 | } 136 | } 137 | catch (BadLocationException e) { 138 | // TODO Auto-generated catch block 139 | // e.printStackTrace(); 140 | } 141 | } 142 | }; 143 | it.setDescription("Enclose the selected text in accent marks to form an operator."); 144 | it.setToolTipText(it.getDescription()); 145 | it.setId("frege-editoraction-op"); 146 | return it; 147 | } 148 | 149 | private Action refreshAction(final UniversalEditor uditor) { 150 | Action it = new Action("Refresh") { 151 | public void run() { 152 | UniversalEditor editor = uditor; 153 | if (editor == null) { 154 | IEditorPart ed = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); 155 | if (ed == null) return; 156 | // System.err.println(ed.getClass().getName()); 157 | if (ed instanceof UniversalEditor) 158 | editor = (UniversalEditor) ed; 159 | else return; 160 | } 161 | final UniversalEditor theEditor = editor; 162 | // editor is not null 163 | try { 164 | if (!editor.isEditable()) return; 165 | IParseController pc = editor.getParseController(); 166 | if (pc == null || !(pc instanceof FregeParseController)) return; 167 | final FregeParseController fpc = (FregeParseController) pc; 168 | TGlobal global = fpc.getCurrentAst(); 169 | if (global == null) return; 170 | // global.mem$sub.mem$cache.put(TTree.DNil.it); 171 | // fpc.global = FregeParseController.runSTG(action, global); 172 | 173 | final IDocument document= editor. 174 | getDocumentProvider(). 175 | getDocument(editor.getEditorInput()); 176 | 177 | fpc.resetHash(); 178 | fpc.msgHandler.clearMessages(); 179 | theEditor.removeParserAnnotations(); 180 | document.replace(0,1, document.get(0, 1)); 181 | } 182 | catch (Exception e) { 183 | // e.printStackTrace(); 184 | } 185 | } 186 | }; 187 | it.setDescription("Notify parser about changes in imported modules."); 188 | it.setToolTipText(it.getDescription()); 189 | it.setId("frege-editoraction-refresh"); 190 | return it; 191 | } 192 | 193 | 194 | private Action compAction(final UniversalEditor uditor) { 195 | Action it = new Action("Compile") { 196 | public void run() { 197 | UniversalEditor editor = uditor; 198 | if (editor == null) { 199 | IEditorPart ed = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); 200 | if (ed == null) return; 201 | // System.err.println(ed.getClass().getName()); 202 | if (ed instanceof UniversalEditor) 203 | editor = (UniversalEditor) ed; 204 | else return; 205 | } 206 | // editor is not null 207 | try { 208 | if (!editor.isEditable()) return; 209 | IParseController pc = editor.getParseController(); 210 | if (pc == null) return; 211 | IPath dpath = pc.getPath(); 212 | ISourceProject project = pc.getProject(); 213 | dpath = project != null ? 214 | project.getRawProject().getLocation().append(dpath) 215 | : dpath; 216 | System.err.println("The path is " + dpath); 217 | IWorkspace workspace= ResourcesPlugin.getWorkspace(); 218 | final IFile dfile = workspace.getRoot().getFileForLocation(dpath); 219 | Job job = new Job("Compile " + dpath) { 220 | @Override protected IStatus run(IProgressMonitor monitor) { 221 | if (new FregeBuilder().compiled(dfile, monitor)) 222 | return Status.OK_STATUS; 223 | return Status.CANCEL_STATUS; 224 | } 225 | 226 | }; 227 | job.schedule(); 228 | System.err.println("Job " + job.getName() + " scheduled."); 229 | } 230 | catch (Exception e) { 231 | // e.printStackTrace(); 232 | } 233 | } 234 | }; 235 | it.setDescription("Invoke the builder on the active file."); 236 | it.setToolTipText(it.getDescription()); 237 | it.setId("frege-editoraction-comp"); 238 | return it; 239 | } 240 | 241 | public void contributeToEditorMenu(final UniversalEditor editor, 242 | IMenuManager menuManager) { 243 | IMenuManager languageMenu = new MenuManager("Frege"); 244 | menuManager.add(languageMenu); 245 | languageMenu.add(fgAction(editor)); 246 | languageMenu.add(rgxAction(editor)); 247 | languageMenu.add(opAction(editor)); 248 | languageMenu.add(compAction(editor)); 249 | languageMenu.add(refreshAction(editor)); 250 | } 251 | 252 | public void contributeToMenuBar(UniversalEditor editor, IMenuManager menu) { 253 | // TODO implement contributions and add them to the menu 254 | 255 | } 256 | 257 | public void contributeToStatusLine(final UniversalEditor editor, 258 | IStatusLineManager statusLineManager) { 259 | // TODO add ControlContribution objects to the statusLineManager 260 | } 261 | 262 | public void contributeToToolBar(UniversalEditor editor, 263 | IToolBarManager toolbarManager) { 264 | 265 | Action fg = fgAction(null); 266 | if (toolbarManager.find(fg.getId()) == null) 267 | toolbarManager.add(fg); 268 | Action rgx = rgxAction(null); 269 | if (toolbarManager.find(rgx.getId()) == null) 270 | toolbarManager.add(rgx); 271 | Action op = opAction(null); 272 | if (toolbarManager.find(op.getId()) == null) 273 | toolbarManager.add(op); 274 | Action comp = compAction(null); 275 | if (toolbarManager.find(comp.getId()) == null) 276 | toolbarManager.add(comp); 277 | Action refresh = refreshAction(null); 278 | if (toolbarManager.find(refresh.getId()) == null) 279 | toolbarManager.add(refresh); 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /src/frege/imp/hoverHelper/FregeHoverHelper.java: -------------------------------------------------------------------------------- 1 | package frege.imp.hoverHelper; 2 | 3 | import java.util.List; 4 | 5 | 6 | 7 | 8 | 9 | 10 | import io.usethesource.impulse.editor.AnnotationHoverBase; 11 | // import io.usethesource.impulse.language.ServiceFactory; 12 | import io.usethesource.impulse.parser.IParseController; 13 | import io.usethesource.impulse.parser.ISourcePositionLocator; 14 | // import io.usethesource.impulse.parser.SimpleLPGParseController; 15 | import io.usethesource.impulse.services.IDocumentationProvider; 16 | import io.usethesource.impulse.services.IHoverHelper; 17 | import io.usethesource.impulse.services.IReferenceResolver; 18 | import io.usethesource.impulse.services.base.HoverHelperBase; 19 | // import io.usethesource.impulse.utils.ExtensionException; 20 | // import io.usethesource.impulse.utils.ExtensionFactory; 21 | import org.eclipse.jface.text.BadLocationException; 22 | import org.eclipse.jface.text.source.Annotation; 23 | import org.eclipse.jface.text.source.ISourceViewer; 24 | 25 | // import frege.FregePlugin; 26 | // import frege.imp.parser.FregeParseController; 27 | 28 | public class FregeHoverHelper extends HoverHelperBase implements IHoverHelper { 29 | IReferenceResolver fResolver = new frege.imp.referenceResolvers.FregeReferenceResolver(); 30 | IDocumentationProvider docProvider = new frege.imp.documentation.FregeDocumentationProvider(); 31 | 32 | public String getHoverHelpAt(IParseController parseController, 33 | ISourceViewer srcViewer, int offset) { 34 | // If there are any annotations associated with the line that contains 35 | // the given offset, return those 36 | try { 37 | List annotations = AnnotationHoverBase.getSourceAnnotationsForLine( 38 | srcViewer, srcViewer.getDocument().getLineOfOffset(offset)); 39 | if (annotations != null && annotations.size() > 0) { 40 | // Some annotations have no text, such as breakpoint annotations; 41 | // if that's all we have, then don't bother returning it 42 | String msg = AnnotationHoverBase 43 | .formatAnnotationList(annotations); 44 | if (msg != null) { 45 | return msg; 46 | } 47 | } 48 | } catch (BadLocationException e) { 49 | return "??? (BadLocationException for annotation)"; 50 | } 51 | 52 | // Otherwise, return a message determined directly or indirectly based 53 | // on the node whose representation occurs at the given offset 54 | 55 | // Get the current AST; no AST implies no message 56 | Object ast = parseController.getCurrentAst(); 57 | if (ast == null) 58 | return null; 59 | 60 | // Declare variables used in formulating the message 61 | Object sourceNode = null; // node at current hover point 62 | Object targetNode = null; // node referenced from current hover point 63 | Object helpNode = null; // node for which a help message is to be constructed 64 | String msg = null; // the help message for helpNode 65 | 66 | // Get the node at the given offset; no node implies no message 67 | ISourcePositionLocator nodeLocator = parseController 68 | .getSourcePositionLocator(); 69 | sourceNode = nodeLocator.findNode(ast, offset); 70 | if (sourceNode == null) 71 | return null; 72 | 73 | 74 | if (fResolver != null) { 75 | targetNode = fResolver.getLinkTarget(sourceNode, 76 | parseController); 77 | } 78 | 79 | 80 | // If the target node is not null, provide help based on that; 81 | // otherwise, provide help based on the source node 82 | if (targetNode != null) 83 | helpNode = targetNode; 84 | else 85 | helpNode = sourceNode; 86 | 87 | 88 | // Now need to determine whether the help message should be determined 89 | // based on the text represented by the node or based on some separate 90 | // text provided through an IDocumentationProvider 91 | 92 | if (docProvider != null) { 93 | msg = docProvider.getDocumentation(helpNode, parseController); 94 | if (msg != null) 95 | return msg; 96 | } 97 | 98 | // // Otherwise, base the help message on the text that is represented 99 | // // by the help node 100 | // if (helpNode instanceof ASTNode) { 101 | // ASTNode def = (ASTNode) helpNode; 102 | // msg = getSubstring(parseController, def.getLeftIToken() 103 | // .getStartOffset(), def.getRightIToken().getEndOffset()); 104 | // int maxMsgLen = 80; 105 | // if (msg == null || msg.length() == 0) 106 | // return "No help available"; 107 | // else if (msg.length() <= maxMsgLen) 108 | // return msg; 109 | // else 110 | // return msg.subSequence(0, maxMsgLen) + "..."; 111 | // } else { 112 | // return "No help available"; 113 | // } 114 | return "no help available"; 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/frege/imp/parser/FregeParseController.java: -------------------------------------------------------------------------------- 1 | package frege.imp.parser; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.InputStreamReader; 6 | import java.io.LineNumberReader; 7 | import java.net.URLClassLoader; 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.HashSet; 13 | import java.util.Iterator; 14 | import java.util.List; 15 | import java.util.Set; 16 | import java.util.regex.Matcher; 17 | import java.util.regex.Pattern; 18 | 19 | import org.eclipse.core.runtime.CoreException; 20 | import org.eclipse.core.runtime.IPath; 21 | import org.eclipse.core.runtime.IProgressMonitor; 22 | import org.eclipse.core.runtime.IStatus; 23 | import org.eclipse.core.runtime.NullProgressMonitor; 24 | import org.eclipse.core.runtime.Status; 25 | import org.eclipse.core.runtime.jobs.Job; 26 | import org.eclipse.core.resources.IFile; 27 | import org.eclipse.core.resources.IFolder; 28 | import org.eclipse.core.resources.IMarker; 29 | import org.eclipse.core.resources.IProject; 30 | import org.eclipse.core.resources.IResource; 31 | import org.eclipse.core.resources.ResourcesPlugin; 32 | import org.eclipse.core.resources.IWorkspace; 33 | import org.eclipse.jdt.core.IClasspathEntry; 34 | import org.eclipse.jdt.core.IJavaProject; 35 | import org.eclipse.jdt.core.JavaCore; 36 | import org.eclipse.jdt.core.JavaModelException; 37 | 38 | import io.usethesource.impulse.builder.MarkerCreatorWithBatching; 39 | import io.usethesource.impulse.builder.ProblemLimit.LimitExceededException; 40 | import io.usethesource.impulse.model.ISourceProject; 41 | import io.usethesource.impulse.parser.IMessageHandler; 42 | import io.usethesource.impulse.parser.IParseController; 43 | // import io.usethesource.impulse.parser.IParser; 44 | import io.usethesource.impulse.parser.ISourcePositionLocator; 45 | import io.usethesource.impulse.parser.ParseControllerBase; 46 | import io.usethesource.impulse.parser.SimpleAnnotationTypeInfo; 47 | import io.usethesource.impulse.preferences.IPreferencesService; 48 | import io.usethesource.impulse.services.IAnnotationTypeInfo; 49 | import io.usethesource.impulse.services.ILanguageSyntaxProperties; 50 | 51 | import org.eclipse.jface.text.IRegion; 52 | 53 | import frege.FregePlugin; 54 | import frege.run8.Lazy; 55 | import frege.run8.Func; 56 | import frege.run8.Thunk; 57 | import frege.run.Kind; 58 | import frege.runtime.Phantom.RealWorld; 59 | import frege.prelude.PreludeBase; 60 | import frege.prelude.PreludeBase.TList.DCons; 61 | import frege.prelude.PreludeBase.TTuple2; 62 | import frege.prelude.PreludeBase.TList; 63 | import frege.control.monad.State.TState; 64 | import frege.control.monad.State.TStateT; 65 | import frege.prelude.PreludeList; 66 | import frege.prelude.PreludeList.IListView_$lbrack$rbrack; 67 | import frege.compiler.enums.Flags.TFlag; 68 | import frege.compiler.enums.Flags.IEnum_Flag; 69 | import frege.compiler.types.Global.TGlobal; 70 | import frege.compiler.types.Global.TMessage; 71 | import frege.compiler.types.Global.TOptions; 72 | import frege.compiler.types.Positions.TPosition; 73 | import frege.compiler.types.Global.TSeverity; 74 | import frege.compiler.types.Global.TSubSt; 75 | import frege.compiler.types.Tokens.TToken; 76 | import frege.compiler.common.CompilerOptions; 77 | import frege.ide.Utilities; 78 | import frege.imp.builders.FregeBuilder; 79 | import frege.imp.preferences.FregePreferencesConstants; 80 | import frege.lib.Modules.TRTree; 81 | import frege.lib.Modules.TY; 82 | import frege.data.Bits.TBitSet; 83 | 84 | 85 | /** 86 | * NOTE: This version of the Parse Controller is for use when the Parse 87 | * Controller and corresponding Node Locator are generated separately from 88 | * a corresponding set of LPG grammar templates and possibly in the absence 89 | * of the lexer, parser, and AST-related types that would be generated from 90 | * those templates. It is assumed that either a) the Controller will be 91 | * used with a suitable set of lexer, parser, and AST-related types 92 | * that are provided by some means other than LPG, or b) the Controller will 93 | * be used with a set of lexer, parser, and AST types that have been, or will 94 | * be, separately generated based on LPG. In order to enable this version of 95 | * the Parse Controller to compile, dummy lexer, parser, and AST-related types 96 | * have been included as member types in the Controller. These types are not 97 | * operational and are merely placeholders for types that would support a 98 | * functioning implementation. Apart from the inclusion of these dummy types, 99 | * this representation of the Parse Controller is the same as that used 100 | * with LPG. 101 | * 102 | * @author Stan Sutton (suttons@us.ibm.com) 103 | * @since May 1, 2007 Addition of marker types 104 | * @since May 10, 2007 Conversion IProject -> ISourceProject 105 | * @since May 15, 2007 Addition of dummy types 106 | */ 107 | public class FregeParseController extends ParseControllerBase implements 108 | IParseController { 109 | 110 | public static class TokensIterator implements Iterator { 111 | /** current token array */ 112 | final private TToken[] toks; 113 | private IRegion region; 114 | private int inx; 115 | 116 | /** check if token is within region */ 117 | public static boolean within(TToken tok, IRegion region) { 118 | return (TToken.offset(tok) + TToken.value(tok).length() >= region.getOffset() 119 | && TToken.offset(tok) <= region.getOffset() + region.getLength()); 120 | } 121 | 122 | /** construct an Iterator */ 123 | public TokensIterator(TToken[] it, IRegion reg) { 124 | toks = it; 125 | region = reg; 126 | inx = 0; 127 | while (inx < toks.length) { 128 | TToken t = toks[inx]; 129 | if (within(t, reg)) break; 130 | inx++; 131 | } 132 | } 133 | 134 | 135 | 136 | @Override 137 | public boolean hasNext() { 138 | // skip { ; } 139 | // inx = skipBraces(toks, inx); 140 | // we have a next if we are not the empty list and the token is in the region 141 | return inx < toks.length 142 | && within(toks[inx], region); 143 | } 144 | 145 | @Override 146 | public TToken next() { 147 | // give back next token 148 | if (inx < toks.length) { 149 | return toks[inx++]; 150 | } 151 | return null; 152 | } 153 | 154 | @Override 155 | public void remove() { 156 | throw new UnsupportedOperationException("TokensIterator"); 157 | } 158 | } 159 | 160 | public static class FregeData { 161 | private String sp = "."; 162 | private String fp = "."; 163 | private String bp = "."; 164 | private String prefix = ""; 165 | private IPath projectPath = null; 166 | private IJavaProject javaProject = null; 167 | private ISourceProject project = null; 168 | public FregeData(ISourceProject sourceProject) { 169 | project = sourceProject; 170 | 171 | if (project != null) { 172 | final String projName = sourceProject.getName(); 173 | 174 | // find out if the preferences specify "project:pfx" 175 | // and take pfx as prefix, if so 176 | IPreferencesService service = FregePlugin.getInstance().getPreferencesService(); 177 | if (service != null) { 178 | String option = service.getStringPreference(FregePreferencesConstants.P_PREFIX); 179 | if (option != null 180 | && projName != null 181 | && option.startsWith(projName) 182 | && option.length() >= 2+projName.length() 183 | && option.charAt(projName.length())==':') { 184 | prefix = option.substring(1+projName.length()); 185 | System.err.println("sourceProject=" + project.getName() 186 | + ", prefix=" + prefix); 187 | } 188 | } 189 | 190 | IProject rp = project.getRawProject(); 191 | 192 | // System.out.println("The raw project has type: " + jp.getClass()); 193 | IWorkspace workspace = ResourcesPlugin.getWorkspace(); 194 | IPath wroot = workspace.getRoot().getLocation(); 195 | // IProjectNatureDescriptor[] nds = workspace.getNatureDescriptors(); 196 | boolean isJava = false; 197 | 198 | try { 199 | isJava = rp.hasNature("org.eclipse.jdt.core.javanature"); 200 | 201 | } catch (CoreException e) { 202 | // e.printStackTrace(); 203 | // System.out.println("The " + nd.getNatureId() + " is not supported, or so it seems."); 204 | } 205 | 206 | if (isJava) { 207 | IJavaProject jp = JavaCore.create(rp); 208 | javaProject = jp; 209 | projectPath = jp.getPath(); 210 | try { 211 | IResource bpres = workspace.getRoot().findMember(jp.getOutputLocation()); 212 | bp = bpres != null 213 | ? bpres.getLocation().toString() 214 | : wroot.append(jp.getOutputLocation()).toPortableString(); 215 | IClasspathEntry[] cpes = jp.getResolvedClasspath(true); 216 | fp = bp; 217 | sp = "."; 218 | for (IClasspathEntry cpe: cpes) { 219 | if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) { 220 | if (sp.length() > 0) sp += System.getProperty("path.separator"); 221 | sp += cpe.getPath().makeRelativeTo(jp.getPath()).toString(); 222 | } 223 | else { 224 | if (fp.length() > 0) fp += System.getProperty("path.separator"); 225 | 226 | IResource res = workspace.getRoot().findMember(cpe.getPath()); 227 | String lib = res != null ? res.getLocation().toString() : "no res"; 228 | String lib1 = cpe.getPath().toString(); 229 | String lib2 = cpe.getPath().makeRelativeTo(jp.getPath()).toString(); 230 | String lib3 = cpe.getPath().makeRelativeTo(wroot).makeRelative().toString(); 231 | String lib4 = cpe.getPath().makeRelativeTo(wroot).toString(); 232 | String lib5 = cpe.getPath().makeRelativeTo(wroot).makeAbsolute().toString(); 233 | if (new java.io.File(lib).exists()) fp += lib; 234 | else if (new java.io.File(lib1).exists()) fp += lib1; 235 | else if (new java.io.File(lib2).exists()) fp += lib2; 236 | else if (new java.io.File(lib3).exists()) fp += lib3; 237 | else if (new java.io.File(lib4).exists()) fp += lib4; 238 | else if (new java.io.File(lib5).exists()) fp += lib5; 239 | else { 240 | System.err.println("WHOA!!! Neither of the following do exist: " 241 | + lib + ", " + lib1 + ", " + lib2 + ", " + lib3 242 | + ", " + lib4 + ", " + lib5); 243 | System.err.println("JavaProject.getPath: " + jp.getPath()); 244 | } 245 | } 246 | } 247 | } catch (JavaModelException e) { 248 | } catch (NullPointerException np) { 249 | } 250 | } 251 | } 252 | if (fp.equals("")) fp="."; 253 | if (sp.equals("")) sp="."; 254 | } 255 | public IPath getProjectPath() { return projectPath; } 256 | /** 257 | * The source path always includes the project directory, as otherwise source resolution in 258 | * linked directories will work only if one links below a source directory, which may not be 259 | * possible always. 260 | * @return the sp 261 | */ 262 | public String getSp() { 263 | return sp; 264 | } 265 | /** 266 | * @return the fp 267 | */ 268 | public String getFp() { 269 | return fp; 270 | } 271 | /** 272 | * @return the bp 273 | */ 274 | public String getBp() { 275 | return bp; 276 | } 277 | 278 | /** 279 | * @return the java project 280 | */ 281 | public IJavaProject getJp() { return javaProject; } 282 | 283 | /** 284 | * @return the prefix for this project 285 | */ 286 | public String getPrefix() { return prefix; } 287 | 288 | /** 289 | * get all frege source files in the work space 290 | */ 291 | public List getAllSources(final String hint) { 292 | final FregeBuilder builder = new FregeBuilder(); 293 | final Set result = new HashSet(); 294 | try { 295 | project.getRawProject() 296 | .getWorkspace().getRoot() 297 | .accept(builder.fResourceVisitor); 298 | } catch (CoreException e) { 299 | // problems getting the file names 300 | return new ArrayList(result); 301 | } 302 | LineNumberReader rdr = null; 303 | for (IFile file : builder.fChangedSources) try { 304 | rdr = null; 305 | rdr = new LineNumberReader(new InputStreamReader(file.getContents(true))); 306 | String line; 307 | java.util.regex.Pattern pat = Pattern.compile("\\b(package|module)\\s+((\\w|\\.)+)"); 308 | while ((line = rdr.readLine()) != null) { 309 | Matcher m = pat.matcher(line); 310 | if (m.find()) { 311 | String p = m.group(2); 312 | if (p.startsWith(hint)) 313 | result.add(p); 314 | } 315 | } 316 | rdr.close(); rdr = null; 317 | } catch (Exception e) { 318 | if (rdr != null) 319 | try { 320 | rdr.close(); 321 | } catch (IOException e1) { 322 | rdr = null; 323 | } 324 | rdr = null; 325 | } 326 | ArrayList sorted = new ArrayList(result); 327 | Collections.sort(sorted); 328 | return sorted; 329 | } 330 | /** 331 | * look for a path that contains the source code for pack 332 | */ 333 | public IPath getSource(final String pack) { 334 | final String fr = pack.replaceAll("\\.", "/") + ".fr"; 335 | // final String[] srcs = getSp().split(System.getProperty("path.separator")); 336 | final FregeBuilder builder = new FregeBuilder(); 337 | try { 338 | project.getRawProject() 339 | // .getWorkspace().getRoot() 340 | .accept(builder.fResourceVisitor); 341 | } catch (CoreException e) { 342 | // problems getting the file names 343 | return null; 344 | } 345 | for (IFile file : builder.fChangedSources) { 346 | IPath it = file.getFullPath(); 347 | if (it.toString().endsWith(fr)) return it; 348 | } 349 | /* 350 | for (String sf: srcs) { 351 | final IPath p = new Path(sf + "/" + fr); 352 | 353 | final IResource toRes = project.getRawProject().findMember(p); 354 | 355 | if (toRes != null && toRes instanceof IFile) { 356 | final IFile to = (IFile) toRes; 357 | return to.getFullPath(); 358 | } 359 | } 360 | */ 361 | return null; 362 | } 363 | } 364 | 365 | public FregeParseController() { 366 | super(FregePlugin.getInstance().getLanguageID()); 367 | } 368 | 369 | private int timeout; 370 | private TGlobal global, goodglobal; 371 | private int hash = 0; 372 | private int leng = 0; 373 | private boolean tokensIteratorDone = false; 374 | private final ISourcePositionLocator fSourcePositionLocator 375 | = new FregeSourcePositionLocator(this); 376 | private final SimpleAnnotationTypeInfo fSimpleAnnotationTypeInfo 377 | = new SimpleAnnotationTypeInfo(); 378 | public IMessageHandler msgHandler = null; 379 | private FregeData fregeData = null; 380 | private static Map>> packs = new HashMap<>(); 381 | 382 | void initPacks() { 383 | boolean make = false; 384 | synchronized (packs) { 385 | make = packs.get(fregeData.getBp()) == null; 386 | if (make) { 387 | // Object value = PreludeBase.TST.performUnsafe(EclipseUtil.getpacks()); 388 | packs.put(fregeData.getBp(), frege.lib.Modules.noPacks); 389 | } 390 | } 391 | if (make) { 392 | Job job = new Job("Getting Modules") { 393 | public IStatus run(IProgressMonitor moni) { 394 | moni.worked(10); 395 | TY> value = 396 | PreludeBase.TST.performUnsafe( 397 | Utilities.initRoot( 398 | fregeData.getFp() 399 | )).call(); 400 | moni.worked(75); 401 | synchronized (packs) { 402 | packs.put(fregeData.getBp(),value); 403 | } 404 | System.err.println("Job done, value=" + value); 405 | moni.done(); 406 | return Status.OK_STATUS; 407 | } 408 | }; 409 | job.schedule(); 410 | } 411 | } 412 | 413 | public TY> ourRoot() { 414 | synchronized (packs) { 415 | return packs.get(fregeData.getBp()); 416 | } 417 | } 418 | 419 | public static TY> ourRoot(FregeParseController parser) { 420 | return parser.ourRoot(); 421 | } 422 | 423 | public void justCompiled() { 424 | synchronized (packs) { 425 | TY> x = ourRoot(); 426 | TY> y = PreludeBase.TST 427 | .performUnsafe( 428 | Utilities.justCompiled( 429 | TGlobal.unpack(global, TGlobal.thisPack(global)), 430 | TSubSt.loader(TGlobal.sub(global)), 431 | x)) 432 | .call(); 433 | packs.put(fregeData.getBp(), y); 434 | } 435 | } 436 | 437 | /** 438 | * @author ingo 439 | * @return the frege data structure 440 | */ 441 | public FregeData getFD() { return fregeData; } 442 | /** 443 | * tell if we have errors 444 | */ 445 | public static int errors(TGlobal global) { return global == null ? 1 : TGlobal.errors(global); } 446 | 447 | /** 448 | * tell how far we are advanced 449 | */ 450 | public static int achievement(TGlobal global) { 451 | if (global == null) return 0; 452 | final TSubSt sub = TGlobal.sub(global); 453 | return 2 * TSubSt.nextPass(sub) - (errors(global) > 0 ? 1 : 0); 454 | } 455 | 456 | /** 457 | * run a {@link frege.prelude.PreludeBase.TState} action and return the new TGlobal state 458 | * @return the new state 459 | */ 460 | public static TGlobal runSTG(TState action, TGlobal g) { 461 | TTuple2 r = TState.run(action, g).call(); 462 | return r.mem2.call() ; 463 | } 464 | 465 | /** 466 | * Run a {@link frege.prelude.PreludeBase.TState} action and return the result. 467 | * The state must not be changed by the action. 468 | * @return the result 469 | */ 470 | public static A funSTG(TState action, TGlobal g) { 471 | TTuple2 r = TState.run(action, g).call(); 472 | return r.mem1.call(); 473 | } 474 | 475 | /** 476 | * run a {@link frege.prelude.PreludeBase.TStateT TGlobal IO} action and return the new TGlobal state 477 | * @return the new state 478 | */ 479 | public static TGlobal runSTIO( 480 | TStateT, A> action, TGlobal g) { 481 | Kind.U, TTuple2> k = TStateT.run(action, g).call(); 482 | Func.U> r = Func.coerceU(k); 483 | TTuple2 t = r.apply(Thunk.lazyWorld).call(); 484 | return t.mem2.call(); 485 | } 486 | 487 | /** 488 | * Run a {@link frege.prelude.PreludeBase.TState} action and return the result. 489 | * The state must not be changed by the action. 490 | * @return the result 491 | */ 492 | public static A funSTIO( 493 | TStateT, A> action, 494 | TGlobal g) { 495 | Kind.U, TTuple2> k = TStateT.run(action, g).call(); 496 | Func.U> r = Func.coerceU(k); 497 | TTuple2 t = r.apply(Thunk.lazyWorld).call(); 498 | return t.mem1.call(); 499 | } 500 | 501 | /** 502 | * @param filePath Project-relative path of file 503 | * @param project Project that contains the file 504 | * @param handler A message handler to receive error messages (or any others) 505 | * from the parser 506 | */ 507 | public void initialize(IPath filePath, ISourceProject project, 508 | IMessageHandler handler) { 509 | super.initialize(filePath, project, handler); 510 | IPath fullFilePath = project != null ? 511 | project.getRawProject().getLocation().append(filePath) 512 | : filePath; 513 | 514 | global = frege.prelude.PreludeBase.TST 515 | .performUnsafe( 516 | CompilerOptions.eclipseOptions.call()) 517 | .call(); 518 | 519 | fregeData = new FregeData(project); 520 | initPacks(); 521 | createLexerAndParser(fullFilePath, project); 522 | 523 | msgHandler = handler; 524 | } 525 | 526 | public FregeParseController getParser() { 527 | new Exception("getParser: called").printStackTrace(System.out); 528 | return null; // parser; 529 | } 530 | 531 | 532 | public ISourcePositionLocator getNodeLocator() { 533 | return fSourcePositionLocator; 534 | } 535 | 536 | 537 | 538 | private void createLexerAndParser(IPath filePath, ISourceProject project) { 539 | System.err.println("createLexerAndParser: " + filePath.toPortableString()); 540 | System.err.println("classpath: " + System.getProperty("java.class.path")); 541 | 542 | 543 | final FregeData data = fregeData; 544 | final String fp = data.getFp(); 545 | final String bp = data.getBp(); 546 | final String sp = data.getSp(); 547 | final IPath pp = data.getProjectPath(); 548 | final IPath wk = ResourcesPlugin.getWorkspace().getRoot().getLocation(); 549 | final String src = pp != null ? filePath 550 | .makeRelativeTo(wk) 551 | .makeAbsolute() 552 | .makeRelativeTo(pp).toString() : filePath.toString(); 553 | 554 | // set source file into global 555 | global = TGlobal.upd$options(global, TOptions.upd$source( 556 | TGlobal.options(global), 557 | src)); 558 | 559 | System.err.println("project Path: " + pp); 560 | System.err.println("source File: " + src); 561 | 562 | System.err.println("FregePath: " + fp); 563 | global = TGlobal.upd$options(global, TOptions.upd$path( 564 | TGlobal.options(global), 565 | frege.java.util.Regex.TRegex.splitted( 566 | CompilerOptions.pathRE.call(), 567 | fp))); 568 | System.err.println("SourcePath: " + sp); 569 | global = TGlobal.upd$options(global, TOptions.upd$sourcePath( 570 | TGlobal.options(global), 571 | frege.java.util.Regex.TRegex.splitted( 572 | CompilerOptions.pathRE.call(), 573 | sp))); 574 | System.err.println("Destination: " + bp); 575 | global = TGlobal.upd$options(global, TOptions.upd$dir( 576 | TGlobal.options(global), 577 | bp)); 578 | global = runSTIO(Utilities.newLoader, global); 579 | 580 | IPreferencesService service = FregePlugin.getInstance().getPreferencesService(); 581 | if (service != null) { 582 | timeout = service.getIntPreference(FregePreferencesConstants.P_PARSETIMEOUT); 583 | if (service.getBooleanPreference(FregePreferencesConstants.P_INLINE)) { 584 | global = TGlobal.upd$options(global, TOptions.upd$flags( 585 | TGlobal.options(global), 586 | TBitSet.unionE(new IEnum_Flag(), 587 | TOptions.flags(TGlobal.options(global)), 588 | TFlag.INLINE) 589 | )); 590 | } else { 591 | global = TGlobal.upd$options(global, TOptions.upd$flags( 592 | TGlobal.options(global), 593 | TBitSet.differenceE(new IEnum_Flag(), 594 | TOptions.flags(TGlobal.options(global)), 595 | TFlag.INLINE)) 596 | ); 597 | } 598 | if (service.getBooleanPreference(FregePreferencesConstants.P_COMMENTS)) { 599 | global = TGlobal.upd$options(global, TOptions.upd$flags( 600 | TGlobal.options(global), 601 | TBitSet.unionE(new IEnum_Flag(), 602 | TOptions.flags(TGlobal.options(global)), 603 | TFlag.COMMENTS)) 604 | ); 605 | } else { 606 | global = TGlobal.upd$options(global, TOptions.upd$flags( 607 | TGlobal.options(global), 608 | TBitSet.differenceE(new IEnum_Flag(), 609 | TOptions.flags(TGlobal.options(global)), 610 | TFlag.COMMENTS)) 611 | ); 612 | } 613 | if (service.getBooleanPreference(FregePreferencesConstants.P_USEUNICODE)) { 614 | global = TGlobal.upd$options(global, TOptions.upd$flags( 615 | TGlobal.options(global), 616 | TBitSet.unionE(new IEnum_Flag(), 617 | TOptions.flags(TGlobal.options(global)), 618 | TFlag.USEUNICODE)) 619 | ); 620 | } else { 621 | global = TGlobal.upd$options(global, TOptions.upd$flags( 622 | TGlobal.options(global), 623 | TBitSet.differenceE(new IEnum_Flag(), 624 | TOptions.flags(TGlobal.options(global)), 625 | TFlag.USEUNICODE)) 626 | ); 627 | } 628 | if (service.getBooleanPreference(FregePreferencesConstants.P_USEGREEK)) { 629 | global = TGlobal.upd$options(global, TOptions.upd$flags( 630 | TGlobal.options(global), 631 | TBitSet.unionE(new IEnum_Flag(), 632 | TOptions.flags(TGlobal.options(global)), 633 | TFlag.USEGREEK)) 634 | ); 635 | } else { 636 | global = TGlobal.upd$options(global, TOptions.upd$flags( 637 | TGlobal.options(global), 638 | TBitSet.differenceE(new IEnum_Flag(), 639 | TOptions.flags(TGlobal.options(global)), 640 | TFlag.USEGREEK)) 641 | ); 642 | } 643 | if (service.getBooleanPreference(FregePreferencesConstants.P_USEFRAKTUR)) { 644 | global = TGlobal.upd$options(global, TOptions.upd$flags( 645 | TGlobal.options(global), 646 | TBitSet.unionE(new IEnum_Flag(), 647 | TOptions.flags(TGlobal.options(global)), 648 | TFlag.USEFRAKTUR)) 649 | ); 650 | } else { 651 | global = TGlobal.upd$options(global, TOptions.upd$flags( 652 | TGlobal.options(global), 653 | TBitSet.differenceE(new IEnum_Flag(), 654 | TOptions.flags(TGlobal.options(global)), 655 | TFlag.USEFRAKTUR)) 656 | ); 657 | } 658 | final String prefix = fregeData.getPrefix(); 659 | if (prefix != null && prefix.length() > 0) { 660 | global = TGlobal.upd$options(global, TOptions.upd$prefix( 661 | TGlobal.options(global), prefix)); 662 | } 663 | } 664 | else timeout = 250; 665 | goodglobal = global; 666 | } 667 | 668 | public void resetHash() { 669 | leng = 0; 670 | hash = 0; 671 | tokensIteratorDone = false; 672 | global = runSTIO(Utilities.refreshPackages.call(), global); 673 | System.err.println("packages cleared"); 674 | } 675 | 676 | /** 677 | * The msgHandler must be in place 678 | */ 679 | synchronized public TGlobal parse(String contents, boolean scanOnly, 680 | IProgressMonitor monitor) { 681 | 682 | long t0 = System.nanoTime(); 683 | long te = 0; 684 | long t1 = 0; 685 | TList< 686 | TTuple2< 687 | TStateT< 688 | TGlobal, 689 | Func.U, 690 | TTuple2>, 691 | String>> passes = null; 692 | DCons< 693 | TTuple2< 694 | TStateT< 695 | TGlobal, 696 | Func.U, 697 | TTuple2>, 698 | String>> pass = null; 699 | int index; 700 | 701 | { 702 | 703 | if (monitor.isCanceled()) return global; 704 | 705 | if (contents.length() == leng && contents.hashCode() == hash) { 706 | return global; // nothing really updated here 707 | } 708 | 709 | 710 | msgHandler.clearMessages(); 711 | 712 | final IProgressMonitor myMonitor = monitor; 713 | Func.U cancel = ((final Lazy x) -> myMonitor.isCanceled() ? Thunk.lazyTrue : Thunk.lazyFalse); 714 | /* 715 | Func.U cancel = new Func.U() { 716 | public Lazy apply(Lazy realworld) { 717 | return myMonitor.isCanceled() ? Thunk.lazyTrue : Thunk.lazyFalse; 718 | } 719 | }; 720 | */ 721 | /* 722 | Func.U cancel = new Func.U.D() { 723 | public Lazy apply(Lazy realworld) { 724 | return myMonitor.isCanceled() ? Thunk.lazyTrue : Thunk.lazyFalse; 725 | } 726 | };*/ 727 | 728 | global = TGlobal.upd$sub(global, TSubSt.upd$cancelled( 729 | TGlobal.sub(global), 730 | cancel)); 731 | global = TGlobal.upd$sub(global, TSubSt.upd$numErrors(TGlobal.sub(global), 0)); 732 | global = TGlobal.upd$sub(global, TSubSt.upd$resErrors(TGlobal.sub(global), 0)); 733 | 734 | passes = frege.compiler.Main.passes.call(); 735 | 736 | monitor.beginTask(this.getClass().getName() + " parsing", 737 | 1 + IListView_$lbrack$rbrack.length(passes)); 738 | 739 | index = 0; 740 | 741 | while (!monitor.isCanceled() 742 | && (pass = passes.asCons()) != null 743 | && errors(global) == 0 744 | && index < 2) { // do lexer and parser synchronized 745 | t1 = System.nanoTime(); 746 | index++; 747 | passes = pass.mem2.call(); 748 | final TTuple2< 749 | TStateT< 750 | TGlobal, 751 | Func.U, 752 | TTuple2>, 753 | String> adx = pass.mem1.call(); 754 | if (index == 1) { 755 | final TState> action = Utilities.lexPassIDE(contents); 756 | final TGlobal g = runSTG(action, global); 757 | final String desc = adx.mem2.call(); 758 | te = System.nanoTime(); 759 | System.err.println(desc + " took " 760 | + (te-t1)/1000000 + "ms, cumulative " 761 | + (te-t0)/1000000 + "ms"); 762 | 763 | monitor.worked(1); 764 | global = runSTG(Utilities.passDone.call(), g); 765 | } 766 | else { 767 | final TStateT< 768 | TGlobal, 769 | Func.U, 770 | TTuple2> action = adx.mem1.call(); 771 | final String desc = adx.mem2.call(); 772 | final TGlobal g = runSTIO(action, global); 773 | te = System.nanoTime(); 774 | System.err.println(desc + " took " 775 | + (te-t1)/1000000 + "ms, cumulative " 776 | + (te-t0)/1000000 + "ms"); 777 | 778 | monitor.worked(1); 779 | global = runSTG(Utilities.passDone.call(), g); 780 | } 781 | } 782 | if (achievement(global) >= achievement(goodglobal)) 783 | goodglobal = global; // when opening a file with errors 784 | else { 785 | // update token array in goodglobal 786 | TToken[] toks = TSubSt.toks(TGlobal.sub(global)); 787 | goodglobal = TGlobal.upd$sub(goodglobal, TSubSt.upd$toks( 788 | TGlobal.sub(goodglobal), toks)); 789 | } 790 | // Array gtoks = TSubSt.toks(TGlobal.sub(global)); 791 | // System.err.println("global.toks==good.toks is " + (toks == gtoks)); 792 | } 793 | 794 | int needed = (int) ((te-t0) / 1000000); 795 | 796 | if (scanOnly && timeout - needed > 0 && errors(global) == 0 && !monitor.isCanceled()) 797 | try { Thread.sleep(timeout - needed); } catch (InterruptedException e) {} 798 | t0 = System.nanoTime() - (te-t0); 799 | 800 | 801 | while (!monitor.isCanceled() 802 | && errors(global) == 0 803 | && (pass = passes.asCons()) != null) { // do the rest unsynchronized 804 | t1 = System.nanoTime(); 805 | passes = pass.mem2.call(); 806 | index++; 807 | final TTuple2< 808 | TStateT< 809 | TGlobal, 810 | Func.U, 811 | TTuple2>, 812 | String> adx = pass.mem1.call(); 813 | final TStateT< 814 | TGlobal, 815 | Func.U, 816 | TTuple2> action = adx.mem1.call(); 817 | final String desc = adx.mem2.call(); 818 | final TGlobal g = runSTIO(action, global); 819 | te = System.nanoTime(); 820 | System.err.println(desc + " took " 821 | + (te-t1)/1000000 + "ms, cumulative " 822 | + (te-t0)/1000000 + "ms"); 823 | 824 | monitor.worked(1); 825 | global = runSTG(Utilities.passDone.call(), g); 826 | 827 | if (achievement(global) >= achievement(goodglobal)) 828 | goodglobal = global; 829 | else if (index >= 6) { 830 | // give token resolve table to goodglobal 831 | goodglobal = TGlobal.upd$sub(goodglobal, TSubSt.upd$idKind( 832 | TGlobal.sub(goodglobal), TSubSt.idKind(TGlobal.sub(global)))); 833 | // give locals to goodglobals 834 | goodglobal = TGlobal.upd$locals(goodglobal, TGlobal.locals(global)); 835 | } 836 | if (scanOnly && desc.startsWith("type check")) { 837 | goodglobal = global; 838 | break; 839 | } 840 | } 841 | 842 | leng = contents.length(); 843 | hash = contents.hashCode(); 844 | return global; 845 | } 846 | 847 | @Override 848 | public TGlobal getCurrentAst() { 849 | // System.err.println("delivered goodglobal"); 850 | return global; 851 | } 852 | 853 | synchronized public TGlobal getGoodAst() { 854 | // System.err.println("delivered goodglobal"); 855 | return goodglobal; 856 | } 857 | 858 | @Override 859 | public TGlobal parse(String input, IProgressMonitor monitor) { 860 | MarkerCreatorWithBatching mcwb = msgHandler instanceof MarkerCreatorWithBatching ? 861 | (MarkerCreatorWithBatching) msgHandler : null; 862 | // when we build, we'll get a MarkerCreatorWithBatching 863 | // Hence, if we do not have one, we just scan&parse, otherwise we do a full compile 864 | TGlobal g = parse(input, mcwb == null, monitor); 865 | int u = TGlobal.unique(g); 866 | System.err.printf("frege parse: done, unique=%d, adding errors ", u); 867 | tokensIteratorDone = false; 868 | TList msgs = PreludeList.reverse(TSubSt.messages(TGlobal.sub(g))); 869 | int maxmsgs = 9; 870 | 871 | // Check we are opening file in project first 872 | if (getProject() != null) { 873 | String fregecJar = null; 874 | 875 | final String[] fp = fregeData.getFp().split(System.getProperty("path.separator")); 876 | // final String correct = frege.FregePlugin.fregeLib; 877 | 878 | for (int i=0; i < fp.length;i++) { 879 | if (fp[i].endsWith("fregec.jar")) { 880 | fregecJar = fp[i]; 881 | fregecJar = java.util.regex.Pattern.compile("\\\\").matcher(fregecJar).replaceAll("/"); 882 | break; 883 | } 884 | } 885 | 886 | // emit an error here if we don't have the correct fregec.jar 887 | if (fregecJar == null) { 888 | if (mcwb != null) try { 889 | mcwb.addMarker(IMarker.SEVERITY_ERROR, 890 | "fregec.jar is missing in the build path." 891 | + "Please 'Enable Frege Builder' from the Project context menu.", 892 | 1, 0, 10); 893 | } catch (LimitExceededException e) { 894 | // leck mich 895 | } 896 | else msgHandler.handleSimpleMessage("fregec.jar is missing in the build path." 897 | + "Please 'Enable Frege Builder' from the Project context menu.", 898 | 0, 10, 0, 0, 0, 0); 899 | } 900 | else if (!fregecJar.equals(frege.FregePlugin.fregeLib)) { 901 | if (mcwb != null) try { 902 | mcwb.addMarker(IMarker.SEVERITY_ERROR, 903 | "Build Path references unexpected " + fregecJar, 904 | 1, 0, 1); 905 | mcwb.addMarker(IMarker.SEVERITY_ERROR, 906 | "It should be " + frege.FregePlugin.fregeLib, 907 | 1, 1, 2); 908 | mcwb.addMarker(IMarker.SEVERITY_ERROR, 909 | "1. Please remove " + fregecJar + " from Build Path", 910 | 1, 2, 3); 911 | mcwb.addMarker(IMarker.SEVERITY_ERROR, 912 | "2. Please 'Enable Frege Builder' from the Project context menu.", 913 | 1, 3, 4); 914 | } catch (LimitExceededException e) { 915 | // leck mich 916 | } 917 | else { 918 | msgHandler.handleSimpleMessage("Build Path references unexpected " + fregecJar, 919 | 0, 1, 0, 0, 0, 0); 920 | msgHandler.handleSimpleMessage("It should be " + frege.FregePlugin.fregeLib, 921 | 1, 2, 0, 0, 0, 0); 922 | msgHandler.handleSimpleMessage("1. Please remove " + fregecJar + " from Build Path", 923 | 2, 3, 0, 0, 0, 0); 924 | msgHandler.handleSimpleMessage("2. Please 'Enable Frege Builder' from the Project context menu.", 925 | 3, 4, 0, 0, 0, 0); 926 | } 927 | } 928 | } 929 | 930 | while (!monitor.isCanceled() && maxmsgs > 0) { 931 | DCons node = msgs.asCons(); 932 | if (node == null) break; 933 | msgs = node.mem2.call(); 934 | TMessage msg = node.mem1.call(); 935 | if (mcwb != null) { 936 | // do also warnings and hints 937 | int sev = IMarker.SEVERITY_ERROR; 938 | if (TMessage.level(msg) == TSeverity.HINT) sev = IMarker.SEVERITY_INFO; 939 | else if (TMessage.level(msg) == TSeverity.WARNING) 940 | sev = IMarker.SEVERITY_WARNING; 941 | try { 942 | mcwb.addMarker(sev, 943 | TMessage.text(msg) 944 | .replaceAll("\n", " "), 945 | TToken.line( TPosition.first(TMessage.pos(msg)) ), 946 | TPosition.start(TMessage.pos(msg)), 947 | TPosition.end(TMessage.pos(msg))); 948 | } catch (LimitExceededException e) { 949 | break; 950 | } 951 | continue; 952 | } 953 | // normal message handling 954 | if (TMessage.level(msg) != TSeverity.ERROR) continue; 955 | maxmsgs--; 956 | System.err.print("."); 957 | msgHandler.handleSimpleMessage(TMessage.text(msg), 958 | TPosition.start(TMessage.pos(msg)), 959 | TPosition.end(TMessage.pos(msg))-1, 960 | 0, 0, 0, 0); 961 | } 962 | if (mcwb == null) { 963 | monitor.done(); 964 | } 965 | System.err.println(" returning to imp framework"); 966 | return g; 967 | } 968 | 969 | @Override 970 | synchronized public Iterator getTokenIterator(IRegion region) { 971 | System.err.print("getTokenIterator(): " + 972 | (global != null ? TGlobal.thisPack(global) : "???")); 973 | if (!tokensIteratorDone) { 974 | System.err.println(" some"); 975 | tokensIteratorDone = true; 976 | return new TokensIterator(TSubSt.toks(TGlobal.sub(global)), region); 977 | } 978 | else { 979 | System.err.println(" none"); 980 | return null; // new TokensIterator(new frege.runtime.Array(0), region); 981 | } 982 | } 983 | 984 | @Override 985 | public ISourcePositionLocator getSourcePositionLocator() { 986 | return fSourcePositionLocator; 987 | } 988 | 989 | @Override 990 | public IAnnotationTypeInfo getAnnotationTypeInfo() { 991 | return fSimpleAnnotationTypeInfo; 992 | } 993 | 994 | private ILanguageSyntaxProperties lsp; 995 | /** 996 | * @return an implementation of {@link ILanguageSyntaxProperties} that 997 | * describes certain syntactic features of this language 998 | */ 999 | @Override 1000 | public ILanguageSyntaxProperties getSyntaxProperties() { 1001 | if (lsp == null) { 1002 | lsp = new ILanguageSyntaxProperties() { 1003 | 1004 | @Override 1005 | public String getSingleLineCommentPrefix() { 1006 | return "--"; 1007 | } 1008 | 1009 | @Override 1010 | public String getIdentifierConstituentChars() { 1011 | return null; 1012 | } 1013 | 1014 | @Override 1015 | public int[] getIdentifierComponents(String ident) { 1016 | return null; 1017 | } 1018 | 1019 | @Override 1020 | public String[][] getFences() { 1021 | return new String[][] { {"(", ")"}, {"{", "}"}, {"[", "]"}}; 1022 | } 1023 | 1024 | @Override 1025 | public String getBlockCommentStart() { 1026 | return "{-"; 1027 | } 1028 | 1029 | @Override 1030 | public String getBlockCommentEnd() { 1031 | return "-}"; 1032 | } 1033 | 1034 | @Override 1035 | public String getBlockCommentContinuation() { 1036 | return null; 1037 | } 1038 | 1039 | @Override 1040 | public boolean isIdentifierStart(char ch) { 1041 | return Character.isJavaIdentifierStart(ch); 1042 | } 1043 | 1044 | @Override 1045 | public boolean isIdentifierPart(char ch) { 1046 | return Character.isJavaIdentifierPart(ch); 1047 | } 1048 | 1049 | @Override 1050 | public boolean isWhitespace(char ch) { 1051 | return Character.isSpaceChar(ch); 1052 | } 1053 | 1054 | @Override 1055 | public IRegion getDoubleClickRegion(int offset, 1056 | IParseController pc) { 1057 | // Auto-generated method stub 1058 | return null; 1059 | } 1060 | 1061 | }; 1062 | } 1063 | return lsp; 1064 | } 1065 | public synchronized final int getHash() { 1066 | return hash; 1067 | } 1068 | public synchronized final int getLeng() { 1069 | return leng; 1070 | } 1071 | 1072 | /** 1073 | * look for a path that contains the source code for pack in the context of this parser 1074 | */ 1075 | public IPath getSource(final String pack) { 1076 | // find it in the sources of this project 1077 | final IPath psrc = getFD().getSource(pack); 1078 | if (psrc != null) return psrc; 1079 | // get it via classloader 1080 | final String fr = pack.replaceAll("\\.", "/") + ".fr"; // the file name 1081 | final String segments[] = pack.split("\\."); 1082 | if (this.fProject == null) return null; // too bad, doesn't work with project. 1083 | // final IProject rp = this.fProject.getRawProject(); 1084 | final IJavaProject jp = getFD().getJp(); 1085 | IWorkspace workspace = ResourcesPlugin.getWorkspace(); 1086 | // IPath wroot = workspace.getRoot().getLocation(); 1087 | 1088 | IFile newsrc = null; 1089 | IPath srcpath = null; 1090 | IPath binPath = null; 1091 | try { 1092 | binPath = jp.getOutputLocation(); 1093 | } catch (JavaModelException e) { 1094 | return null; 1095 | } 1096 | 1097 | srcpath = binPath.append(fr); 1098 | newsrc = workspace.getRoot().getFile(srcpath); 1099 | if (newsrc == null) return null; // couldn't get file handle here 1100 | if (newsrc.exists()) return srcpath; 1101 | 1102 | IFolder folder = workspace.getRoot().getFolder(binPath); 1103 | // System.err.println("Parser.getSource start in folder " + folder.getLocation()); 1104 | InputStream stream = null; 1105 | 1106 | try { 1107 | // create the intermediate directories 1108 | for (int i=0; i < segments.length-1; i++) { 1109 | binPath = binPath.append(segments[i]); 1110 | folder = workspace.getRoot().getFolder(binPath); 1111 | // System.err.println("Parser.getSource continue in folder " + folder.getLocation()); 1112 | if (folder.exists()) { 1113 | // System.err.println("Parser.getSource exists " + folder.getLocation()); 1114 | } 1115 | else { 1116 | // System.err.println("Parser.getSource creating " + folder.getLocation()); 1117 | folder.create(true, true, null); 1118 | } 1119 | } 1120 | 1121 | final TSubSt subst = TGlobal.sub(this.global); 1122 | final URLClassLoader loader = TSubSt.loader(subst); 1123 | stream = loader.getResourceAsStream(fr); 1124 | if (stream == null) return null; // not here :-( 1125 | newsrc.create(stream, IResource.FORCE | IResource.DERIVED, new NullProgressMonitor()); 1126 | } catch (CoreException e) { 1127 | System.err.println(e.getMessage()); 1128 | return null; 1129 | } finally { 1130 | try { if (stream != null) stream.close(); } catch (IOException ioe) {} 1131 | } 1132 | return srcpath; 1133 | } 1134 | 1135 | } 1136 | -------------------------------------------------------------------------------- /src/frege/imp/parser/FregeSourcePositionLocator.java: -------------------------------------------------------------------------------- 1 | package frege.imp.parser; 2 | 3 | import org.eclipse.core.runtime.IPath; 4 | import org.eclipse.core.runtime.Path; 5 | 6 | import io.usethesource.impulse.editor.ModelTreeNode; 7 | import io.usethesource.impulse.parser.ISourcePositionLocator; 8 | 9 | import frege.compiler.types.Tokens.IShow_Token; 10 | import frege.compiler.types.Global; 11 | import frege.compiler.types.Global.TGlobal; 12 | import frege.compiler.types.QNames; 13 | import frege.compiler.types.QNames.TQName; 14 | import frege.compiler.types.Positions.TPosition; 15 | import frege.compiler.types.Global.TSubSt; 16 | import frege.compiler.types.Tokens.TToken; 17 | import frege.compiler.types.Symbols.TSymbolT; 18 | import frege.imp.referenceResolvers.FregeReferenceResolver; 19 | import frege.imp.tree.ITreeItem; 20 | 21 | 22 | /** 23 | * NOTE: This version of the ISourcePositionLocator is for use when the Source 24 | * Position Locator and corresponding Parse Controller are generated separately from 25 | * a corresponding set of LPG grammar templates and possibly in the absence 26 | * of the lexer, parser, and AST-related types that would be generated from 27 | * those templates. To enable compilation of the Locator and Controller, 28 | * dummy types have been defined as member types of the Controller in place 29 | * of possibly missing lexer, parser, and AST-related types. This version 30 | * of the Node Locator refers to some of those types. When those types 31 | * are replaced by real implementation types, the Locator must be modified 32 | * to refer to those. Apart from statements to import needed types from 33 | * the Parse Controller, this SourcePositionLocator is the same as that used 34 | * with LPG. 35 | * @see the corresponding ParseController type 36 | * 37 | * @author Stan Sutton (suttons@us.ibm.com) 38 | * @since May 15, 2007 39 | */ 40 | public class FregeSourcePositionLocator implements ISourcePositionLocator { 41 | // private final Object[] fNode = new Object[1]; 42 | // private int fStartOffset; 43 | // private int fEndOffset; 44 | final private FregeParseController parser; 45 | 46 | public FregeSourcePositionLocator(FregeParseController parser) { 47 | this.parser = parser; 48 | } 49 | 50 | public Object findNode(Object ast, int offset) { 51 | return findNode(ast, offset, offset); 52 | } 53 | 54 | /** 55 | * Given an offset, find the index of the previous token. 56 | * @param arr an Array of Tokens 57 | * @param offset the offset in the text 58 | * @return the index of the very next previous token 59 | */ 60 | public static int previous(TToken[] arr, int before) { 61 | int from = 0; 62 | int to = arr.length; 63 | 64 | while (from +2 < to) { 65 | int it = (from + to) / 2; 66 | // if (it==from || it == to) break; 67 | // System.err.println("previous: before=" + before + ", from=" + from + ", to=" + to); 68 | TToken at = tokenAt(arr, it); 69 | int off = TToken.offset(at); 70 | // System.err.println("previous: it=" + it + ", token=" + IShow_Token.show(at)); 71 | 72 | if (off >= before) { // its more left 73 | to = it; continue; 74 | } 75 | from = it; 76 | } 77 | // linear search down 78 | while (to >= 0) { 79 | // System.err.println("previous: before=" + before + ", to=" + to); 80 | TToken at = tokenAt(arr, to); 81 | if (at == null || TToken.col(at) == 0) { to--; continue; } // no inserted ';' and '}' 82 | // System.err.println("previous: token=" + IShow_Token.show(at)); 83 | if (TToken.offset(at) < before) return to; 84 | to--; 85 | } 86 | return (-1); 87 | } 88 | /** 89 | * Binary search for a token that starts at start and ends not after end. 90 | * 91 | * @param arr an Array of Tokens 92 | * @param start start of selected range 93 | * @param end end of selected range (inklusive) 94 | * @return the index of a Token or (-1) if not found 95 | */ 96 | public static int binsearch(TToken[] arr, int start, int end) { 97 | int from = 0; 98 | int to = arr.length; 99 | while (from < to) { 100 | int it = (from + to) / 2; 101 | TToken at = arr[it]; 102 | int off = TToken.offset(at); 103 | int len = TToken.length(at); 104 | if (off + len <= start) { // the searched token is more right 105 | from = it+1; continue; 106 | } 107 | if (off > end) { // its more left 108 | to = it; continue; 109 | } 110 | if (off + len >= start && off+len > end) return it; 111 | return (-1); 112 | } 113 | return (-1); 114 | } 115 | 116 | /** 117 | * return the token at a given index or null 118 | */ 119 | public static TToken tokenAt(TToken[] arr, int at) { 120 | if (at < 0 || at >= arr.length) 121 | return null; 122 | return arr[at]; 123 | } 124 | 125 | public Object findNode(Object ast, int startOffset, int endOffset) { 126 | System.err.print("findNode( " + ast + ", " + startOffset + ", " + endOffset + " ) called: "); 127 | if (ast != null && ast instanceof TGlobal) { 128 | // find out the token we are working with 129 | TGlobal global = (TGlobal) ast; 130 | TToken[] arr = TSubSt.toks( TGlobal.sub(global) ); 131 | int at = binsearch(arr, startOffset, endOffset); 132 | TToken res = tokenAt(arr, at); 133 | if (res == null) 134 | System.err.println(" no such token"); 135 | else { 136 | System.err.println(IShow_Token.show(res)); 137 | } 138 | return res; 139 | } 140 | else { 141 | System.err.println("no compiler state"); 142 | } 143 | return null; 144 | } 145 | 146 | public int getStartOffset(TToken node) { return node==null ? 0 : TToken.offset(node); } 147 | public int getStartOffset(TPosition pos) { return TPosition.start(pos); } 148 | public int getStartOffset(Object node) { 149 | 150 | if (node != null && node instanceof TToken) 151 | return TToken.offset((TToken)node); 152 | 153 | if (node != null && node instanceof ITreeItem) 154 | return TPosition.start( ((ITreeItem)node).getPosition() ); 155 | 156 | if (node != null && node instanceof FregeReferenceResolver.Namespace) { 157 | final FregeReferenceResolver.Namespace nmsp = (FregeReferenceResolver.Namespace) node; 158 | if (nmsp.pack.equals(TGlobal.thisPack(nmsp.g))) 159 | return TToken.offset(TPosition.first(Global.packageStart(nmsp.g).call())); 160 | return -1; // different package 161 | } 162 | 163 | if (node != null && node instanceof FregeReferenceResolver.Symbol) { 164 | final FregeReferenceResolver.Symbol sym = (FregeReferenceResolver.Symbol) node; 165 | final TQName qname = TSymbolT.name(sym.sym); 166 | final boolean our = TGlobal.our(sym.g, qname); 167 | final int off = getStartOffset(TSymbolT.pos(sym.sym)); 168 | System.err.println("getStartOffSet( " + QNames.IShow_QName.show(qname) 169 | + " ), our=" + our 170 | + " ), off=" + off); 171 | return off; 172 | // return -1; // different package 173 | } 174 | 175 | if (node != null && node instanceof ModelTreeNode) return 0; 176 | System.err.println("getStartOffSet( " + node + " ) called"); 177 | return 0; 178 | } 179 | 180 | public int getEndOffset(TPosition pos) { return TPosition.end(pos)-1; } 181 | public int getEndOffset(Object node) { return getStartOffset(node) + getLength(node) - 1; } 182 | 183 | public int getLength(TToken node) { return TToken.length(node); } 184 | public int getLength(TPosition pos) { return TPosition.end(pos)-TPosition.start(pos); } 185 | 186 | public int getLength(Object node) { 187 | if (node != null && node instanceof TToken) 188 | return getLength((TToken)node); 189 | 190 | if (node != null && node instanceof ITreeItem) 191 | return getLength(((ITreeItem)node).getPosition()); 192 | 193 | if (node != null && node instanceof FregeReferenceResolver.Namespace) { 194 | final FregeReferenceResolver.Namespace nmsp = (FregeReferenceResolver.Namespace) node; 195 | return nmsp.pack.length(); 196 | } 197 | 198 | if (node != null && node instanceof FregeReferenceResolver.Symbol) { 199 | final FregeReferenceResolver.Symbol sym = (FregeReferenceResolver.Symbol) node; 200 | // final TQName qname = TSymbol.M.name(sym.sym); 201 | // final boolean our = TQName.M.our(qname, sym.g); 202 | return getLength(TSymbolT.pos(sym.sym)); 203 | // return -1; // different package 204 | } 205 | 206 | if (node != null && node instanceof ModelTreeNode) return 0; 207 | System.err.println("getLength( " + node + " ) called"); 208 | return 1; 209 | } 210 | 211 | public IPath getPath(Object node) { 212 | if (node != null && node instanceof FregeReferenceResolver.Namespace) { 213 | final FregeReferenceResolver.Namespace nmsp = (FregeReferenceResolver.Namespace) node; 214 | final IPath p = parser.getSource(nmsp.pack); 215 | System.err.println("getPath( " + nmsp.pack + " ), path=" + p); 216 | 217 | return p; 218 | } 219 | if (node != null && node instanceof FregeReferenceResolver.Symbol) { 220 | final FregeReferenceResolver.Symbol sym = (FregeReferenceResolver.Symbol) node; 221 | final TQName qname = TSymbolT.name(sym.sym); 222 | final boolean our = TGlobal.our(sym.g, qname); 223 | final String pack = our ? TGlobal.thisPack(sym.g) : TQName.getpack(qname); 224 | IPath p = parser.getSource(pack); 225 | System.err.println("getPath( " + QNames.IShow_QName.show(qname) 226 | + " ), our=" + our + ", pack=" + pack + ", path=" + p); 227 | return p; 228 | } 229 | return new Path(""); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/frege/imp/preferences/FregeInstancePreferencesTab.java: -------------------------------------------------------------------------------- 1 | 2 | package frege.imp.preferences; 3 | 4 | import java.util.List; 5 | import java.util.ArrayList; 6 | import org.eclipse.swt.SWT; 7 | import org.eclipse.swt.layout.GridData; 8 | import org.eclipse.swt.widgets.Composite; 9 | import io.usethesource.impulse.preferences.*; 10 | import io.usethesource.impulse.preferences.fields.*; 11 | 12 | 13 | /** 14 | * The instance level preferences tab. 15 | */ 16 | public class FregeInstancePreferencesTab extends InstancePreferencesTab { 17 | 18 | public FregeInstancePreferencesTab(IPreferencesService prefService) { 19 | super(prefService, false); 20 | } 21 | 22 | /** 23 | * Creates specific preference fields with settings appropriate to 24 | * the instance preferences level. 25 | * 26 | * Overrides an unimplemented method in PreferencesTab. 27 | * 28 | * @return An array that contains the created preference fields 29 | * 30 | */ 31 | protected FieldEditor[] createFields(TabbedPreferencesPage page, Composite parent) 32 | { 33 | List fields = new ArrayList(); 34 | 35 | 36 | FontFieldEditor sourceFont = fPrefUtils.makeNewFontField( 37 | page, this, fPrefService, 38 | "instance", "sourceFont", "Editor Font", 39 | "Editor font", 40 | parent, 41 | true, true, 42 | false); 43 | fields.add(sourceFont); 44 | 45 | IntegerFieldEditor tabWidth = fPrefUtils.makeNewIntegerField( 46 | page, this, fPrefService, 47 | "instance", "tabWidth", "Tabulator Width", 48 | "Tells how many spaces the tab key will insert.", 49 | parent, 50 | true, true, 51 | true, "4", 52 | false); 53 | fields.add(tabWidth); 54 | 55 | GridData data = new GridData(); 56 | data.horizontalAlignment = SWT.END; 57 | data.widthHint = 128; 58 | 59 | 60 | BooleanFieldEditor spacesForTabs = fPrefUtils.makeNewBooleanField( 61 | page, this, fPrefService, 62 | "instance", "spacesForTabs", "Tab inserts spaces", 63 | "Is it strongly suggested to not have tabulator characters in Frege source code.", 64 | parent, 65 | true, true, 66 | true, true, 67 | false); 68 | fields.add(spacesForTabs); 69 | 70 | BooleanFieldEditor enableInline = fPrefUtils.makeNewBooleanField( 71 | page, this, fPrefService, 72 | "instance", "enableInline", "Enable Inline", 73 | "Optimize by inlining functions option to the compiler.", 74 | parent, 75 | true, true, 76 | true, false, 77 | false); 78 | fields.add(enableInline); 79 | 80 | 81 | BooleanFieldEditor enableComments = fPrefUtils.makeNewBooleanField( 82 | page, this, fPrefService, 83 | "instance", "enableComments", "Enable Comments", 84 | "Create commented source code. Builds will take much longer.", 85 | parent, 86 | true, true, 87 | true, false, 88 | false); 89 | fields.add(enableComments); 90 | 91 | BooleanFieldEditor italicImports = fPrefUtils.makeNewBooleanField( 92 | page, this, fPrefService, 93 | "instance", "italicImports", "Show imported items in italics", 94 | "Gives a visual clue about whether a name was imported.", 95 | parent, 96 | true, true, 97 | true, false, 98 | false); 99 | fields.add(italicImports); 100 | 101 | BooleanFieldEditor boldNS = fPrefUtils.makeNewBooleanField( 102 | page, this, fPrefService, 103 | "instance", "boldNS", "Show name spaces in bold face", 104 | "Gives a visual clue about whether a qualifier is not a type, but a namespace.", 105 | parent, 106 | true, true, 107 | true, false, 108 | false); 109 | fields.add(boldNS); 110 | 111 | BooleanFieldEditor unicode = fPrefUtils.makeNewBooleanField( 112 | page, this, fPrefService, 113 | "instance", "useUnicode", "Use Unicode Symbols", 114 | "Use ∀ and → instead of 'forall' and -> when showing types (not yet implemented)", 115 | parent, 116 | true, true, 117 | true, false, 118 | false); 119 | fields.add(unicode); 120 | 121 | BooleanFieldEditor greek = fPrefUtils.makeNewBooleanField( 122 | page, this, fPrefService, 123 | "instance", "useGreek", "Greek Type Variables", 124 | "Construct type variable names from greek letters when showing types (not yet implemented)", 125 | parent, 126 | true, true, 127 | true, false, 128 | false); 129 | fields.add(greek); 130 | 131 | BooleanFieldEditor fraktur = fPrefUtils.makeNewBooleanField( 132 | page, this, fPrefService, 133 | "instance", "useFraktur", "Fraktur Type Variables", 134 | "Construct type variable names from fraktur letters when showing types (not yet implemented)", 135 | parent, 136 | true, true, 137 | true, false, 138 | false); 139 | fields.add(fraktur); 140 | ColorFieldEditor docuColor = fPrefUtils.makeNewColorField( 141 | page, this, fPrefService, 142 | "instance", "docuColor", "Documentation", 143 | "Color for documentation comments", 144 | parent, 145 | true, true, 146 | false); 147 | docuColor.getLabelControl(docuColor.getParent()).setLayoutData(data); 148 | fields.add(docuColor); 149 | 150 | ColorFieldEditor commColor = fPrefUtils.makeNewColorField( 151 | page, this, fPrefService, 152 | "instance", "commColor", "Comments ", 153 | "Color for ordinary comments", 154 | parent, 155 | true, true, 156 | false); 157 | commColor.getLabelControl(commColor.getParent()).setLayoutData(data); 158 | fields.add(commColor); 159 | 160 | ColorFieldEditor tconColor = fPrefUtils.makeNewColorField( 161 | page, this, fPrefService, 162 | "instance", "tconColor", "Types etc.", 163 | "Color for type constrcutors, type aliases, classes and namespaces", 164 | parent, 165 | true, true, 166 | false); 167 | tconColor.getLabelControl(tconColor.getParent()).setLayoutData(data); 168 | fields.add(tconColor); 169 | 170 | ColorFieldEditor dconColor = fPrefUtils.makeNewColorField( 171 | page, this, fPrefService, 172 | "instance", "dconColor", "Constructors ", 173 | "Color for data constrcutor names", 174 | parent, 175 | true, true, 176 | false); 177 | dconColor.getLabelControl(dconColor.getParent()).setLayoutData(data); 178 | fields.add(dconColor); 179 | 180 | 181 | ColorFieldEditor varidColor = fPrefUtils.makeNewColorField( 182 | page, this, fPrefService, 183 | "instance", "varidColor", "Top level vars", 184 | "Color for non-local variables defined in the current package", 185 | parent, 186 | true, true, 187 | false); 188 | varidColor.getLabelControl(varidColor.getParent()).setLayoutData(data); 189 | fields.add(varidColor); 190 | 191 | ColorFieldEditor importColor = fPrefUtils.makeNewColorField( 192 | page, this, fPrefService, 193 | "instance", "importColor", "Imported vars", 194 | "Color for variables and functions defined in an imported package", 195 | parent, 196 | true, true, 197 | false); 198 | importColor.getLabelControl(importColor.getParent()).setLayoutData(data); 199 | fields.add(importColor); 200 | 201 | ColorFieldEditor keywordColor = fPrefUtils.makeNewColorField( 202 | page, this, fPrefService, 203 | "instance", "keywordColor", "Reserved words", 204 | "Color for key words.", 205 | parent, 206 | true, true, 207 | false); 208 | keywordColor.getLabelControl(keywordColor.getParent()).setLayoutData(data); 209 | fields.add(keywordColor); 210 | 211 | ColorFieldEditor specialColor = fPrefUtils.makeNewColorField( 212 | page, this, fPrefService, 213 | "instance", "specialColor", "Special symbols ", 214 | "Color for symbols ::, ->, <-, => and |", 215 | parent, 216 | true, true, 217 | false); 218 | specialColor.getLabelControl(specialColor.getParent()).setLayoutData(data); 219 | fields.add(specialColor); 220 | 221 | ColorFieldEditor literalColor = fPrefUtils.makeNewColorField( 222 | page, this, fPrefService, 223 | "instance", "literalColor", "Literal values", 224 | "Colors for literal numbers, strings, characters and regular expressions", 225 | parent, 226 | true, true, 227 | false); 228 | literalColor.getLabelControl(literalColor.getParent()).setLayoutData(data); 229 | fields.add(literalColor); 230 | 231 | ColorFieldEditor errorColor = fPrefUtils.makeNewColorField( 232 | page, this, fPrefService, 233 | "instance", "errorColor", "Lexical errors", 234 | "Color that signals unfinished block comments and quoted constructs", 235 | parent, 236 | true, true, 237 | false); 238 | 239 | errorColor.getLabelControl(errorColor.getParent()).setLayoutData(data); 240 | fields.add(errorColor); 241 | 242 | // RadioGroupFieldEditor tstyle = fPrefUtils.makeNewRadioGroupField( 243 | // page, this, fPrefService, 244 | // "instance", "typeStyle", "Type Presentation Style", 245 | // "Decide how to show types", 246 | // 3, new String[] {"ascii", "greek", "fraktur"}, 247 | // // new String[]{"forall a.a->a", "∀α.α→α", "∀𝖆.𝖆→𝖆"}, 248 | // new String[]{"A", "G", "F"}, 249 | // parent, true, true, false); 250 | // fields.add(tstyle); 251 | 252 | StringFieldEditor prefix = fPrefUtils.makeNewStringField( 253 | page, this, fPrefService, 254 | "instance", "prefix", "Prefix", 255 | "Used in compiler development", 256 | parent, 257 | true, true, 258 | true, "", 259 | false); 260 | fields.add(prefix); 261 | 262 | 263 | IntegerFieldEditor parseTimeout = fPrefUtils.makeNewIntegerField( 264 | page, this, fPrefService, 265 | "instance", "parseTimeout", "Parser Timeout", 266 | "Time in ms before the parser starts after a keystroke.", 267 | parent, 268 | true, true, 269 | true, "250", 270 | false); 271 | fields.add(parseTimeout); 272 | 273 | 274 | return fields.toArray(new FieldEditor[fields.size()]); 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /src/frege/imp/preferences/FregePreferencesConstants.java: -------------------------------------------------------------------------------- 1 | /******************************************/ 2 | /* WARNING: GENERATED FILE - DO NOT EDIT! */ 3 | /******************************************/ 4 | package frege.imp.preferences; 5 | 6 | // import io.usethesource.impulse.preferences.PreferenceConstants; 7 | 8 | /** 9 | * Constant definitions for preferences. 10 | * 11 | * The preferences service uses Strings as keys for preference values, 12 | * so Strings defined here are used here to designate preference fields. 13 | * These strings are generated automatically from a preferences specification. 14 | */ 15 | public class FregePreferencesConstants { 16 | public static final String P_SOURCEFONT = "sourceFont"; 17 | // public static final String P_SPACESFORTABS = PreferenceConstants.P_SPACES_FOR_TABS; 18 | public static final String P_TABWITH = "tabulatorWidth"; 19 | public static final String P_INLINE = "enableInline"; 20 | public static final String P_COMMENTS = "enableComments"; 21 | public static final String P_PARSETIMEOUT = "parseTimeout"; 22 | public static final String P_PREFIX = "prefix"; 23 | public static final String P_ITALICIMPORTS = "italicImports"; 24 | public static final String P_BOLDNS = "boldNS"; 25 | public static final String P_DOCUCOLOR = "docuColor"; 26 | public static final String P_COMMCOLOR = "commColor"; 27 | public static final String P_TCONCOLOR = "tconColor"; 28 | public static final String P_DCONCOLOR = "dconColor"; 29 | public static final String P_VARIDCOLOR = "varidColor"; 30 | public static final String P_IMPORTCOLOR = "importColor"; 31 | public static final String P_KEYWORDCOLOR = "keywordColor"; 32 | public static final String P_SPECIALCOLOR = "specialColor"; 33 | public static final String P_LITERALCOLOR = "literalColor"; 34 | public static final String P_ERRORCOLOR = "errorColor"; 35 | public static final String P_USEUNICODE = "useUnicode"; 36 | public static final String P_USEGREEK = "useGreek"; 37 | public static final String P_USEFRAKTUR = "useFraktur"; 38 | } 39 | -------------------------------------------------------------------------------- /src/frege/imp/preferences/FregePreferencesInitializer.java: -------------------------------------------------------------------------------- 1 | /******************************************/ 2 | /* WARNING: GENERATED FILE - DO NOT EDIT! */ 3 | /******************************************/ 4 | package frege.imp.preferences; 5 | 6 | import io.usethesource.impulse.preferences.PreferencesInitializer; 7 | import io.usethesource.impulse.preferences.IPreferencesService; 8 | import org.eclipse.jface.resource.StringConverter; 9 | import org.eclipse.swt.graphics.RGB; 10 | 11 | import frege.FregePlugin; 12 | 13 | /** 14 | * Initializations of default values for preferences. 15 | */ 16 | public class FregePreferencesInitializer extends PreferencesInitializer { 17 | /** 18 | * Convert a hex number to RGB 19 | */ 20 | public static RGB hexRGB(int color) { 21 | final int red = (color & 0xff0000) >> 16; 22 | final int green = (color & 0x00ff00) >> 8; 23 | final int blue = (color & 0x0000ff); 24 | return new RGB(red, green, blue); 25 | } 26 | /* 27 | * (non-Javadoc) 28 | * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() 29 | */ 30 | public void initializeDefaultPreferences() { 31 | IPreferencesService service = FregePlugin.getInstance().getPreferencesService(); 32 | 33 | // in the following, we set some "light solarized colours as defaults" 34 | String base01 = StringConverter.asString(hexRGB(0x586e75)); 35 | String brgreen = base01; 36 | String base1 = StringConverter.asString(hexRGB(0x93a1a1)); 37 | String brcyan = base1; 38 | String yellow = StringConverter.asString(hexRGB(0xb58900)); 39 | String orange = StringConverter.asString(hexRGB(0xcb4b16)); 40 | String red = StringConverter.asString(hexRGB(0xdc322f)); 41 | String magenta = StringConverter.asString(hexRGB(0xd33682)); 42 | String violet = StringConverter.asString(hexRGB(0x6c71c4)); 43 | String blue = StringConverter.asString(hexRGB(0x268bd2)); 44 | String cyan = StringConverter.asString(hexRGB(0x2aa198)); 45 | String green = StringConverter.asString(hexRGB(0x859900)); 46 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_SOURCEFONT, "Consolas"); 47 | service.setIntPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_TABWITH, 4); 48 | service.setIntPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_PARSETIMEOUT, 250); 49 | // service.setBooleanPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_SPACESFORTABS, true); 50 | service.setBooleanPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_INLINE, true); 51 | service.setBooleanPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_INLINE, false); 52 | service.setBooleanPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_USEUNICODE, false); 53 | service.setBooleanPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_USEGREEK, false); 54 | service.setBooleanPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_USEFRAKTUR, false); 55 | service.setBooleanPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_ITALICIMPORTS, true); 56 | service.setBooleanPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_BOLDNS, true); 57 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_DOCUCOLOR, brgreen); 58 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_COMMCOLOR, brcyan); 59 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_TCONCOLOR, orange); 60 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_DCONCOLOR, green); 61 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_VARIDCOLOR, blue); 62 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_IMPORTCOLOR, violet); 63 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_KEYWORDCOLOR, magenta); 64 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_SPECIALCOLOR, magenta); 65 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_LITERALCOLOR, cyan); 66 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_ERRORCOLOR, red); 67 | service.setStringPreference(IPreferencesService.DEFAULT_LEVEL, FregePreferencesConstants.P_PREFIX, ""); 68 | 69 | /* 70 | System.err.println("darkYellow is " + darkYellow); 71 | System.err.println("darkRed is " + darkRed); 72 | System.err.println("black is " + black); 73 | System.err.println("red is " + red); 74 | System.err.println("darkMagenta is " + darkMagenta); 75 | System.err.println("darkGreen is " + darkGreen); 76 | System.err.println("darkCyan is " + darkCyan); 77 | */ 78 | } 79 | 80 | /* 81 | * Clear (remove) any preferences set on the given level. 82 | */ 83 | public void clearPreferencesOnLevel(String level) { 84 | IPreferencesService service = FregePlugin.getInstance().getPreferencesService(); 85 | service.clearPreferencesAtLevel(level); 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/frege/imp/preferences/FregePreferencesPage.java: -------------------------------------------------------------------------------- 1 | /******************************************/ 2 | /* WARNING: GENERATED FILE - DO NOT EDIT! */ 3 | /******************************************/ 4 | package frege.imp.preferences; 5 | 6 | import org.eclipse.swt.widgets.TabFolder; 7 | import io.usethesource.impulse.preferences.IPreferencesService; 8 | import io.usethesource.impulse.preferences.PreferencesInitializer; 9 | import io.usethesource.impulse.preferences.PreferencesTab; 10 | import io.usethesource.impulse.preferences.TabbedPreferencesPage; 11 | import frege.FregePlugin; 12 | 13 | /** 14 | * A preference page class. 15 | */ 16 | public class FregePreferencesPage extends TabbedPreferencesPage { 17 | public FregePreferencesPage() { 18 | super(); 19 | prefService = FregePlugin.getInstance().getPreferencesService(); 20 | } 21 | 22 | protected PreferencesTab[] createTabs(IPreferencesService prefService, 23 | TabbedPreferencesPage page, TabFolder tabFolder) { 24 | PreferencesTab[] tabs = new PreferencesTab[1]; 25 | 26 | FregeInstancePreferencesTab instanceTab = new FregeInstancePreferencesTab(prefService); 27 | instanceTab.createTabContents(page, tabFolder); 28 | tabs[0] = instanceTab; 29 | 30 | return tabs; 31 | } 32 | 33 | public PreferencesInitializer getPreferenceInitializer() { 34 | return new FregePreferencesInitializer(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/frege/imp/preferences/frege.pfsp.txt: -------------------------------------------------------------------------------- 1 | // 2 | // This preferences-specification template declares some example 3 | // preference fields and some conditional controls for enabling 4 | // one field based on another. 5 | // 6 | package frege.imp.preferences; 7 | 8 | tabs { 9 | // There is one tab for each level of preference values: 10 | // - "default" (as specified by "defvalue" attributes below) 11 | // - "configuration" (shared by all Eclipse invocations from the same installation) 12 | // - "instance" (shared by all Eclipse invocations using on the same workspace) 13 | // - "project" (project-specific settings) 14 | // 15 | // A value for a given preference key may be set at any or all of these levels. 16 | // 17 | // Value accesses are made from a client-specified context (one of the above 4 levels, 18 | // though most likely either "instance" or "project"). 19 | // 20 | // If no value for the given preference key exists at the specified level, it is inherited 21 | // from the next level above, going up to the default level (which always has a value), if 22 | // necessary, to find a value. 23 | // 24 | // Clients identify the desired context level for their queries when the client creates the 25 | // PreferencesService instance. Typically, the context will be either the instance (workspace) 26 | // context, or the context of some specific project. 27 | // 28 | // "in" tabs appear in the preference page; "out" tabs do not. 29 | // The following combination gives the "classic" Eclipse behavior. 30 | default out { } 31 | configuration out { } 32 | instance in { } 33 | project out { } 34 | } 35 | 36 | page Frege { 37 | // TODO Customize the preference fields and their attributes 38 | fields { 39 | // START_HERE 40 | font sourceFont { 41 | label "Editor Font"; 42 | defvalue "Consolas" 10 normal; 43 | } 44 | int tabWidth { 45 | label "Tabulator Width"; 46 | defvalue 4; 47 | } 48 | boolean spacesForTabs { 49 | label "Tab inserts spaces"; 50 | defvalue true; 51 | tooltip "Is it strongly suggested to not have tabulator characters in Frege source code."; 52 | } 53 | 54 | color docuColor { label "Documentation color "; } 55 | color commColor { label "Comment color "; } 56 | color conidColor { label "Constructor id color"; } 57 | color varidColor { label "Variable id color "; } 58 | color keywordColor { label "Keyword color "; } 59 | color specialColor { label "Special symbol color"; } 60 | color opColor { label "Operator color "; } 61 | color literalColor { label "Literal color "; } 62 | color errorColor { label "Error token color "; } 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/frege/imp/referenceResolvers/FregeReferenceResolver.java: -------------------------------------------------------------------------------- 1 | package frege.imp.referenceResolvers; 2 | 3 | 4 | import io.usethesource.impulse.parser.IParseController; 5 | import io.usethesource.impulse.services.IReferenceResolver; 6 | import frege.data.TreeMap.TTreeMap; 7 | import frege.compiler.types.Tokens.IShow_Token; 8 | import frege.compiler.types.Tokens.TToken; 9 | import frege.compiler.enums.TokenID.TTokenID; 10 | import frege.compiler.types.Global.TGlobal; 11 | import frege.compiler.types.QNames; 12 | import frege.compiler.types.QNames.TQName; 13 | import frege.compiler.types.Symbols.TSymbolT; 14 | import frege.ide.Utilities; 15 | import frege.imp.parser.FregeParseController; 16 | import frege.prelude.PreludeBase.TEither; 17 | import frege.prelude.PreludeBase.TEither.DLeft; 18 | import frege.prelude.PreludeBase.TEither.DRight; 19 | import frege.prelude.PreludeBase.TMaybe; 20 | import frege.prelude.PreludeBase.TMaybe.DJust; 21 | import frege.run8.Thunk; 22 | 23 | 24 | 25 | public class FregeReferenceResolver implements IReferenceResolver { 26 | 27 | public static class Symbol { 28 | public final TGlobal g; 29 | public final TSymbolT sym; 30 | public Symbol(TGlobal g, TSymbolT sym) { this.g = g; this.sym = sym; } 31 | public String toString() { 32 | String s = FregeParseController.funSTIO( 33 | Utilities.symbolDocumentation(sym), g); 34 | return s; // Data.INice_QName.nicer(TSymbol.M.name(sym), g); 35 | } 36 | } 37 | 38 | public static class Namespace { 39 | public final TGlobal g; 40 | public final String ns; 41 | public final String pack; 42 | public Namespace(TGlobal g, String ns, String p) { 43 | this.g = g; 44 | this.ns = ns; 45 | this.pack = p; 46 | } 47 | public String toString() { 48 | String s = FregeParseController.funSTIO( 49 | Utilities.packDocumentation(Thunk.lazy(pack)), g); 50 | return s; 51 | } 52 | } 53 | 54 | public FregeReferenceResolver() { 55 | } 56 | 57 | /** 58 | * Get the text associated with the given node for use in a link 59 | * from (or to) that node 60 | */ 61 | public String getLinkText(Object node) { 62 | // TODO Replace the following with an implementation suitable to your language and reference types 63 | return "unimplemented"; // node.toString(); 64 | } 65 | 66 | /** 67 | * Get the target for the given source node in the AST produced by the 68 | * given Parse Controller. 69 | */ 70 | public Object getLinkTarget(Object node, IParseController controller) { 71 | TGlobal g = null; 72 | 73 | if (controller != null) { 74 | Object o = controller.getCurrentAst(); 75 | if (o != null && o instanceof TGlobal) g = (TGlobal) o; 76 | } 77 | 78 | if (g != null && node != null && node instanceof TToken) { 79 | TToken tok = (TToken) node; 80 | System.err.println("getLinkTarget: " + IShow_Token.show(tok)); 81 | int tid = TToken.tokid(tok); 82 | if (tid == TTokenID.CHAR && "_".equals(TToken.value(tok))) { 83 | tid = TTokenID.VARID; 84 | tok = TToken.upd$tokid(tok, TTokenID.VARID); 85 | tok = TToken.upd$value(tok, "it"); 86 | } 87 | 88 | // is this '-' ? 89 | final boolean isMinus = tid == TTokenID.CHAR && "-".equals(TToken.value(tok)); 90 | 91 | if (tid != TTokenID.VARID 92 | && tid != TTokenID.CONID 93 | && tid != TTokenID.QUALIFIER 94 | && tid != TTokenID.SOMEOP 95 | && !isMinus 96 | ) return null; 97 | TMaybe> mb = TGlobal.resolved(g, tok); 98 | DJust> just = mb.asJust(); 99 | if (just == null) { 100 | if (isMinus) { 101 | TToken neg = TToken.upd$value( 102 | TToken.upd$tokid(tok, TTokenID.VARID), 103 | "negate"); 104 | mb = TGlobal.resolved(g, neg); 105 | just = mb.asJust(); 106 | if (just == null) return null; 107 | } 108 | else return null; 109 | } 110 | final TEither lr = just.mem1.call(); 111 | final DRight right = lr.asRight(); 112 | if (right != null) { 113 | // this is a QName 114 | TQName q = right.mem1.call(); 115 | final TMaybe> mbsym = TGlobal.findit(g, q).call(); 116 | final DJust> jsym = mbsym.asJust(); 117 | if (jsym == null) return null; // not found? 118 | final TSymbolT sym = jsym.mem1.call(); 119 | System.err.println("getLinkTarget: " + QNames.IShow_QName.show(q)); 120 | return new Symbol(g, sym); 121 | } 122 | final DLeft left = lr.asLeft(); 123 | if (left != null) { 124 | // this is a namespace 125 | String ns = TToken.value(tok); 126 | final TTreeMap tree = TGlobal.namespaces(g); 127 | final TMaybe mbpack = TTreeMap.lookupS(tree, ns); 128 | final DJust jpack = mbpack.asJust(); 129 | if (jpack == null) return null; 130 | String pack = jpack.mem1.call(); 131 | return new Namespace(g, ns, pack); 132 | } 133 | } 134 | 135 | return null; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/frege/imp/tokenColorer/FregeTokenColorer.java: -------------------------------------------------------------------------------- 1 | package frege.imp.tokenColorer; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | import io.usethesource.impulse.parser.IParseController; 6 | import io.usethesource.impulse.preferences.IPreferencesService; 7 | import io.usethesource.impulse.services.ITokenColorer; 8 | import io.usethesource.impulse.services.base.TokenColorerBase; 9 | 10 | import org.eclipse.jface.resource.StringConverter; 11 | import org.eclipse.jface.text.IRegion; 12 | import org.eclipse.jface.text.TextAttribute; 13 | import org.eclipse.swt.SWT; 14 | import org.eclipse.swt.graphics.Color; 15 | import org.eclipse.swt.widgets.Display; 16 | 17 | import frege.FregePlugin; 18 | import frege.compiler.types.QNames.TQName.DLocal; 19 | import frege.compiler.types.Tokens.TToken; 20 | import frege.compiler.types.Global.TGlobal; 21 | import frege.compiler.enums.TokenID.TTokenID; 22 | import frege.compiler.types.QNames.TQName; 23 | import frege.imp.parser.FregeParseController; 24 | import frege.imp.preferences.FregePreferencesConstants; 25 | import frege.prelude.PreludeBase.TEither; 26 | import frege.prelude.PreludeBase.TEither.DRight; 27 | import frege.prelude.PreludeBase.TMaybe; 28 | import frege.prelude.PreludeBase.TMaybe.DJust; 29 | 30 | 31 | 32 | 33 | public class FregeTokenColorer extends TokenColorerBase implements ITokenColorer { 34 | protected final TextAttribute 35 | normalAttribute, impAttribute, iopAttribute, 36 | identAttribute, docuAttribute, 37 | commentAttribute, specialAttribute, 38 | keywordAttribute, literalAttribute, errorAttribute, 39 | nsAttribute, typeAttribute, itypeAttribute, 40 | conAttribute, iconAttribute; 41 | final Pattern pattern = Pattern.compile("^\\W+$"); 42 | 43 | // protected final TextAttribute commentAttribute, stringAttribute; 44 | 45 | public FregeTokenColorer() { 46 | super(); 47 | 48 | Display display = Display.getDefault(); 49 | IPreferencesService service = FregePlugin.getInstance().getPreferencesService(); 50 | 51 | final boolean boldns = service.getBooleanPreference(FregePreferencesConstants.P_BOLDNS); 52 | final boolean italic = service.getBooleanPreference(FregePreferencesConstants.P_ITALICIMPORTS); 53 | 54 | Color docuColor = new Color (display, 55 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_DOCUCOLOR), 56 | display.getSystemColor(SWT.COLOR_DARK_BLUE).getRGB())); 57 | Color commColor = new Color (display, 58 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_COMMCOLOR), 59 | display.getSystemColor(SWT.COLOR_DARK_CYAN).getRGB())); 60 | Color tconColor = new Color (display, 61 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_TCONCOLOR), 62 | display.getSystemColor(SWT.COLOR_DARK_RED).getRGB())); 63 | Color dconColor = new Color (display, 64 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_DCONCOLOR), 65 | display.getSystemColor(SWT.COLOR_DARK_YELLOW).getRGB())); 66 | Color varidColor = new Color (display, 67 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_VARIDCOLOR), 68 | display.getSystemColor(SWT.COLOR_BLACK).getRGB())); 69 | Color importColor = new Color (display, 70 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_IMPORTCOLOR), 71 | display.getSystemColor(SWT.COLOR_BLACK).getRGB())); 72 | Color keywdColor = new Color (display, 73 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_KEYWORDCOLOR), 74 | display.getSystemColor(SWT.COLOR_DARK_MAGENTA).getRGB())); 75 | Color litColor = new Color (display, 76 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_LITERALCOLOR), 77 | display.getSystemColor(SWT.COLOR_DARK_CYAN).getRGB())); 78 | Color errColor = new Color (display, 79 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_ERRORCOLOR), 80 | display.getSystemColor(SWT.COLOR_RED).getRGB())); 81 | Color spcColor = new Color (display, 82 | StringConverter.asRGB(service.getStringPreference(FregePreferencesConstants.P_SPECIALCOLOR), 83 | display.getSystemColor(SWT.COLOR_DARK_MAGENTA).getRGB())); 84 | commentAttribute = new TextAttribute(commColor, null, SWT.NORMAL); 85 | docuAttribute = new TextAttribute(docuColor, null, SWT.ITALIC); 86 | normalAttribute = null; // new TextAttribute(display.getSystemColor(SWT.COLOR_BLACK), null, SWT.NORMAL); 87 | keywordAttribute = new TextAttribute(keywdColor, null, SWT.BOLD); 88 | literalAttribute = new TextAttribute(litColor, null, SWT.NORMAL); 89 | errorAttribute = new TextAttribute(errColor, null, SWT.NORMAL); 90 | specialAttribute = new TextAttribute(spcColor, null, SWT.BOLD); 91 | 92 | identAttribute = new TextAttribute(varidColor, null, SWT.NORMAL); 93 | impAttribute = new TextAttribute(importColor, null, italic ? SWT.ITALIC : SWT.NORMAL); 94 | iopAttribute = new TextAttribute(importColor, null, SWT.NORMAL); 95 | nsAttribute = new TextAttribute(tconColor, null, boldns ? SWT.BOLD : SWT.NORMAL); 96 | typeAttribute = new TextAttribute(tconColor, null, SWT.NORMAL); 97 | itypeAttribute = new TextAttribute(tconColor, null, italic ? SWT.ITALIC : SWT.NORMAL); 98 | conAttribute = new TextAttribute(dconColor, null, SWT.NORMAL); 99 | iconAttribute = new TextAttribute(dconColor, null, italic ? SWT.ITALIC : SWT.NORMAL); 100 | } 101 | 102 | public TextAttribute getKind(FregeParseController controller, TToken tok, TextAttribute normalAttribute) { 103 | TGlobal g = controller.getCurrentAst(); 104 | final TMaybe> mb = TGlobal.resolved(g, tok); 105 | final DJust> just = mb.asJust(); 106 | if (just == null) return normalAttribute; 107 | final TEither et = just.mem1.call(); 108 | final DRight right = et.asRight(); 109 | if (right == null) return nsAttribute; // since it is Left () 110 | final TQName qname = right.mem1.call(); 111 | final DLocal local = qname.asLocal(); 112 | if (local != null) return normalAttribute; // local var 113 | final boolean our = TGlobal.our(g, qname); 114 | final TQName.DTName tname = qname.asTName(); 115 | if (tname != null) return our? typeAttribute : itypeAttribute; 116 | final TQName.DMName mname = qname.asMName(); 117 | if (mname != null && TToken.tokid(tok) == TTokenID.CONID) 118 | return our ? conAttribute : iconAttribute; 119 | final String b = TQName.base(qname); 120 | final boolean op = pattern.matcher(b).find(); 121 | return our ? identAttribute : (op ? iopAttribute : impAttribute); 122 | } 123 | 124 | @Override 125 | public TextAttribute getColoring(IParseController controller, Object o) { 126 | if (o == null) 127 | return null; 128 | return getColoring((FregeParseController) controller, (TToken) o); 129 | } 130 | 131 | public TextAttribute getColoring(final FregeParseController controller, final TToken token) { 132 | final int tid = TToken.tokid(token); 133 | 134 | if (tid >= TTokenID.PACKAGE && tid <= TTokenID.INFIXR) return keywordAttribute; 135 | if (tid == TTokenID.DOCUMENTATION) return docuAttribute; 136 | if (tid == TTokenID.COMMENT) return commentAttribute; 137 | if (tid == TTokenID.VARID && TToken.value(token).equals("_")) 138 | return specialAttribute; 139 | if (tid == TTokenID.CONID 140 | || tid == TTokenID.QUALIFIER 141 | || tid == TTokenID.VARID) { 142 | return getKind(controller, token, normalAttribute); 143 | } 144 | 145 | // if (tid == TTokenID.VARID.j || tid == TTokenID.QVARID.j) return identAttribute; 146 | if (tid >= TTokenID.INTCONST && tid <= TTokenID.REGEXP) return literalAttribute; 147 | if (tid == TTokenID.LEXERROR) return errorAttribute; 148 | 149 | if (tid >= TTokenID.DCOLON && tid <= TTokenID.EARROW) return specialAttribute; 150 | if (tid >= TTokenID.LOP0 && tid <= TTokenID.SOMEOP) 151 | return getKind(controller, token, normalAttribute); 152 | if (tid == TTokenID.CHAR && TToken.value(token).length() > 0) 153 | switch (TToken.value(token).charAt(0)) { 154 | case '_': return specialAttribute; 155 | case '=': return specialAttribute; 156 | case '|': return specialAttribute; 157 | case '\\': return specialAttribute; 158 | case ';': return normalAttribute; 159 | case '(': return normalAttribute; 160 | case ')': return normalAttribute; 161 | case '[': return normalAttribute; 162 | case ']': return normalAttribute; 163 | case '{': return normalAttribute; 164 | case '}': return normalAttribute; 165 | case ',': return normalAttribute; 166 | case '.': return normalAttribute; 167 | case '!': return identAttribute; 168 | case '?': return identAttribute; 169 | case '-': return identAttribute; 170 | default: break; 171 | } 172 | // System.err.println("Don't know how to colour " + IShow_Token.show(token) + " ?"); 173 | return errorAttribute; 174 | } 175 | 176 | public IRegion calculateDamageExtent(IRegion seed) { 177 | System.err.println("calculateDamagExtent: " + seed); 178 | return seed; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/frege/imp/tree/CategoryItem.java: -------------------------------------------------------------------------------- 1 | package frege.imp.tree; 2 | 3 | import org.eclipse.swt.graphics.Image; 4 | 5 | import frege.compiler.types.Positions.TPosition; 6 | 7 | public class CategoryItem implements ITreeItem { 8 | final String label; 9 | final TPosition pos; 10 | 11 | public CategoryItem(String n, TPosition p) { 12 | label = n; pos = p; 13 | } 14 | 15 | @Override 16 | public Image getImage() { 17 | return FregeLabelProvider.OUTLINE_IMAGE; 18 | } 19 | 20 | @Override 21 | public String getLabel() { 22 | return label; 23 | } 24 | 25 | @Override 26 | public TPosition getPosition() { 27 | return pos; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/frege/imp/tree/FregeLabelProvider.java: -------------------------------------------------------------------------------- 1 | package frege.imp.tree; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import org.eclipse.core.resources.IFile; 7 | import org.eclipse.core.resources.IMarker; 8 | import org.eclipse.core.resources.IResource; 9 | import io.usethesource.impulse.editor.ModelTreeNode; 10 | import io.usethesource.impulse.services.ILabelProvider; 11 | import frege.FregePlugin; 12 | import frege.IFregeResources; 13 | import io.usethesource.impulse.utils.MarkerUtils; 14 | import org.eclipse.jface.resource.ImageRegistry; 15 | import org.eclipse.jface.viewers.ILabelProviderListener; 16 | import org.eclipse.swt.graphics.Image; 17 | 18 | 19 | 20 | public class FregeLabelProvider implements ILabelProvider { 21 | private Set fListeners = new HashSet(); 22 | 23 | private static ImageRegistry sImageRegistry = FregePlugin.getInstance() 24 | .getImageRegistry(); 25 | 26 | final public static Image DEFAULT_IMAGE = sImageRegistry 27 | .get(IFregeResources.FREGE_DEFAULT_IMAGE); 28 | final public static Image OUTLINE_IMAGE = sImageRegistry 29 | .get(IFregeResources.FREGE_DEFAULT_OUTLINE_ITEM); 30 | final public static Image PACKAGE_IMAGE = sImageRegistry 31 | .get(IFregeResources.FREGE_PACKAGE_OUTLINE_ITEM); 32 | final public static Image IMPORT_IMAGE = sImageRegistry 33 | .get(IFregeResources.FREGE_IMPORT_OUTLINE_ITEM); 34 | final public static Image TYPE_IMAGE = sImageRegistry 35 | .get(IFregeResources.FREGE_TYPE_OUTLINE_ITEM); 36 | final public static Image CLASS_IMAGE = sImageRegistry 37 | .get(IFregeResources.FREGE_CLASS_OUTLINE_ITEM); 38 | final public static Image INST_IMAGE = sImageRegistry 39 | .get(IFregeResources.FREGE_INST_OUTLINE_ITEM); 40 | final public static Image DATA_IMAGE = sImageRegistry 41 | .get(IFregeResources.FREGE_DATA_OUTLINE_ITEM); 42 | final public static Image CON_IMAGE = sImageRegistry 43 | .get(IFregeResources.FREGE_CON_OUTLINE_ITEM); 44 | final public static Image VAR_IMAGE = sImageRegistry 45 | .get(IFregeResources.FREGE_VAR_OUTLINE_ITEM); 46 | final public static Image LOCAL_IMAGE = sImageRegistry 47 | .get(IFregeResources.FREGE_LOCAL_OUTLINE_ITEM); 48 | final public static Image LINK_IMAGE = sImageRegistry 49 | .get(IFregeResources.FREGE_LINK_OUTLINE_ITEM); 50 | final public static Image[] SYMBOL_IMAGES = new Image[] { 51 | DATA_IMAGE, LINK_IMAGE, CON_IMAGE, CLASS_IMAGE, INST_IMAGE, VAR_IMAGE, TYPE_IMAGE 52 | }; 53 | final public static Image FILE_IMAGE = sImageRegistry 54 | .get(IFregeResources.FREGE_FILE); 55 | final public static Image FILE_WITH_WARNING_IMAGE = sImageRegistry 56 | .get(IFregeResources.FREGE_FILE_WARNING); 57 | final public static Image FILE_WITH_ERROR_IMAGE = sImageRegistry 58 | .get(IFregeResources.FREGE_FILE_ERROR); 59 | final public static Image FILE_WITH_INFO_IMAGE = sImageRegistry 60 | .get(IFregeResources.FREGE_FILE_INFO); 61 | 62 | public Image getImage(Object element) { 63 | if (element instanceof IFile) { 64 | 65 | IFile file = (IFile) element; 66 | int sev = MarkerUtils.getMaxProblemMarkerSeverity(file, 67 | IResource.DEPTH_ONE); 68 | 69 | switch (sev) { 70 | case IMarker.SEVERITY_ERROR: 71 | return FILE_WITH_ERROR_IMAGE; 72 | case IMarker.SEVERITY_WARNING: 73 | return FILE_WITH_WARNING_IMAGE; 74 | // case IMarker.SEVERITY_INFO: 75 | // return FILE_WITH_INFO_IMAGE; 76 | default: 77 | return FILE_IMAGE; 78 | } 79 | } 80 | Object n = (element instanceof ModelTreeNode) 81 | ? ((ModelTreeNode) element).getASTNode() 82 | : element; 83 | 84 | return getImageFor(n); 85 | 86 | } 87 | 88 | public static Image getImageFor(Object n) { 89 | if (n instanceof ITreeItem) 90 | return ((ITreeItem) n).getImage(); 91 | return OUTLINE_IMAGE; 92 | } 93 | 94 | public String getText(Object element) { 95 | Object n = (element instanceof ModelTreeNode) 96 | ? ((ModelTreeNode) element).getASTNode() 97 | : element; 98 | 99 | return getLabelFor(n); 100 | } 101 | 102 | public static String getLabelFor(Object n) { 103 | if (n instanceof ITreeItem) 104 | return ((ITreeItem) n).getLabel(); 105 | return "instance of (" + n.getClass().getName() + ")"; 106 | } 107 | 108 | public void addListener(ILabelProviderListener listener) { 109 | fListeners.add(listener); 110 | } 111 | 112 | public void dispose() { 113 | } 114 | 115 | public boolean isLabelProperty(Object element, String property) { 116 | return false; 117 | } 118 | 119 | public void removeListener(ILabelProviderListener listener) { 120 | fListeners.remove(listener); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/frege/imp/tree/FregeTreeModelBuilder.java: -------------------------------------------------------------------------------- 1 | package frege.imp.tree; 2 | 3 | import io.usethesource.impulse.services.base.TreeModelBuilderBase; 4 | import frege.data.TreeMap.TTreeMap; 5 | import frege.compiler.types.Expression.TExprT; 6 | import frege.compiler.types.Global.TGlobal; 7 | import frege.compiler.types.Positions.TPosition; 8 | import frege.compiler.types.Global.TSubSt; 9 | import frege.compiler.types.Symbols.TSymbolT; 10 | import frege.control.monad.State; 11 | import frege.control.monad.State.TState; 12 | import frege.ide.Utilities; 13 | import frege.imp.parser.FregeParseController; 14 | import frege.prelude.PreludeBase.TList; 15 | import frege.prelude.PreludeBase.TList.DCons; 16 | import frege.prelude.PreludeBase.TMaybe; 17 | import frege.prelude.PreludeBase.TMaybe.DJust; 18 | import frege.prelude.PreludeBase.TTuple3; 19 | 20 | public class FregeTreeModelBuilder extends TreeModelBuilderBase { 21 | private TGlobal prev = null; 22 | @Override 23 | public void visitTree(Object root) { 24 | if (root == null || !(root instanceof TGlobal)) 25 | return; 26 | TGlobal global = (TGlobal) root; 27 | if (prev == null || FregeParseController.achievement(prev) <= FregeParseController.achievement(global)) 28 | prev = global; 29 | else global = prev; 30 | 31 | // fModelRoot = createTopItem(global, ModelTreeNode.DEFAULT_CATEGORY); 32 | 33 | FregeModelVisitor visitor = new FregeModelVisitor(); 34 | 35 | // rootNode.accept(visitor); 36 | visitor.visit(global); 37 | } 38 | 39 | final static public int data = 0; 40 | final static public int link = 1; 41 | final static public int dcon = 2; 42 | final static public int clas = 3; 43 | final static public int inst = 4; 44 | final static public int func = 5; 45 | final static public int type = 6; 46 | final static public String[] categories = new String[] { 47 | "Data Types", "Imported Items", "Constructors", "Type Classes", "Instances", 48 | "Functions and Values", "Type Aliases" 49 | }; 50 | final static public int[] order = new int[] { 51 | link, clas, inst, type, data, dcon, func 52 | }; 53 | 54 | 55 | public class FregeModelVisitor /* extends AbstractVisitor */ { 56 | 57 | public boolean visit(TGlobal g, TTreeMap> env, boolean top) { 58 | final TList> syms = Utilities.symbols(env); 59 | // do one category after the other according to the predefined order 60 | for (int cat : order) { 61 | if (!top) { // avoid unneeded list traversals 62 | if (cat != func && cat != dcon) continue; 63 | } 64 | else if (cat == dcon) continue; 65 | 66 | // go through the list of symbols and do the ones that equal the current category 67 | DCons> elem = syms.asCons(); 68 | boolean found = false; 69 | while (elem != null) { 70 | final TSymbolT sym = elem.mem1.call(); 71 | elem = (elem.mem2.call()).asCons(); 72 | if (sym.constructor() != cat) continue; 73 | if (sym.constructor() == link && TGlobal.our(g, TSymbolT.alias(sym))) continue; 74 | if (top) { // category labels at the top only before first item 75 | if (!found) { 76 | pushSubItem(new CategoryItem(categories[cat], TSymbolT.pos(sym))); 77 | found = true; 78 | } 79 | } 80 | visit(g, sym); 81 | } 82 | if (found) popSubItem(); 83 | found = false; 84 | } 85 | return true; 86 | } 87 | 88 | public boolean visit(TGlobal g, TSymbolT sym) { 89 | pushSubItem(new SymbolItem(g, sym)); 90 | if (TSymbolT.has$env(sym)) visit(g, TSymbolT.env(sym), false); 91 | else if (TSymbolT.has$expr(sym)) { 92 | final TMaybe> mbex = TSymbolT.expr(sym); 93 | final DJust> just = mbex.asJust(); 94 | if (just != null) { 95 | TState lam = just.mem1.call(); 96 | final TExprT expr = State.evalState(lam, g); 97 | visit(g, expr); 98 | } 99 | } 100 | popSubItem(); 101 | return true; 102 | } 103 | 104 | public boolean visit(TGlobal g, TExprT expr) { 105 | // System.err.println("visiting: " + g.toString() + ", " + expr.toString()); 106 | TList> symbols = FregeParseController.funSTG( 107 | Utilities.exprSymbols(expr), g); 108 | DCons> node = symbols.asCons(); 109 | while (node != null) { 110 | TSymbolT sym = node.mem1.call(); 111 | visit(g, sym); 112 | node = node.mem2.call().asCons(); 113 | } 114 | return true; 115 | } 116 | 117 | public boolean visit(TGlobal g) { 118 | final TSubSt sub = TGlobal.sub(g); 119 | final String pack = TSubSt.thisPack(sub); 120 | 121 | pushSubItem(new PackageItem(pack, TSubSt.thisPos(sub))); 122 | if (! "".equals(pack)) { 123 | final TList> pnps = Utilities.imports(g).call(); 124 | DCons> elem = pnps.asCons(); 125 | while (elem != null) { 126 | final TTuple3 tuple = elem.mem1.call(); 127 | elem = elem.mem2.call().asCons(); 128 | final TPosition pos = tuple.mem1.call(); 129 | final String ns = tuple.mem2.call(); 130 | final String p = tuple.mem3.call(); 131 | createSubItem(new ImportItem(pos, ns, p)); 132 | } 133 | } 134 | popSubItem(); 135 | 136 | if (! "".equals(pack)) 137 | return visit(g, 138 | Utilities.thisTab(g), 139 | true); 140 | return true; 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/frege/imp/tree/ITreeItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | *

Items in the tree must have the ability to compute their label, image and position.

3 | */ 4 | package frege.imp.tree; 5 | 6 | import org.eclipse.swt.graphics.Image; 7 | 8 | import frege.compiler.types.Positions.TPosition; 9 | 10 | /** 11 | * @author ingo 12 | * 13 | */ 14 | public interface ITreeItem { 15 | public Image getImage(); 16 | public String getLabel(); 17 | public TPosition getPosition(); 18 | } 19 | -------------------------------------------------------------------------------- /src/frege/imp/tree/ImportItem.java: -------------------------------------------------------------------------------- 1 | package frege.imp.tree; 2 | 3 | import org.eclipse.swt.graphics.Image; 4 | 5 | import frege.compiler.types.Positions.TPosition; 6 | 7 | public class ImportItem implements ITreeItem { 8 | final TPosition pos; 9 | final String ns, pack; 10 | 11 | public ImportItem(TPosition pos, String ns, String pack) { 12 | this.pos = pos; 13 | this.ns = ns; 14 | this.pack = pack; 15 | } 16 | 17 | @Override 18 | public Image getImage() { 19 | return FregeLabelProvider.IMPORT_IMAGE; 20 | } 21 | 22 | @Override 23 | public String getLabel() { 24 | return ns + ": " + pack; 25 | } 26 | 27 | @Override 28 | public TPosition getPosition() { 29 | return pos; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/frege/imp/tree/PackageItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * A String and a TPosition describing a package 3 | */ 4 | package frege.imp.tree; 5 | 6 | import org.eclipse.swt.graphics.Image; 7 | 8 | import frege.compiler.types.Positions.TPosition; 9 | 10 | /** 11 | * @author ingo 12 | * 13 | */ 14 | public class PackageItem implements ITreeItem { 15 | 16 | final public String name; 17 | final public TPosition pos; 18 | 19 | public PackageItem(String n, TPosition p) { name = n; pos = p; } 20 | 21 | @Override 22 | public Image getImage() { 23 | return FregeLabelProvider.PACKAGE_IMAGE; 24 | } 25 | 26 | @Override 27 | public String getLabel() { 28 | // TODO Auto-generated method stub 29 | return name; 30 | } 31 | 32 | @Override 33 | public TPosition getPosition() { 34 | return pos; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/frege/imp/tree/SymbolItem.java: -------------------------------------------------------------------------------- 1 | package frege.imp.tree; 2 | 3 | import org.eclipse.swt.graphics.Image; 4 | 5 | import frege.compiler.types.Global.TGlobal; 6 | import frege.compiler.types.QNames.TQName; 7 | import frege.compiler.enums.Visibility.TVisibility; 8 | import frege.compiler.types.Positions.TPosition; 9 | import frege.compiler.types.Symbols.TSymbolT; 10 | import frege.ide.Utilities; 11 | 12 | public class SymbolItem implements ITreeItem { 13 | final TSymbolT symbol; 14 | final TGlobal global; 15 | 16 | public SymbolItem(TGlobal g, TSymbolT sy) { global = g; symbol = sy; } 17 | 18 | @Override 19 | public Image getImage() { 20 | final int c = symbol.constructor(); 21 | if (c >= 0 && c < FregeLabelProvider.SYMBOL_IMAGES.length) { 22 | Image image = FregeLabelProvider.SYMBOL_IMAGES[c]; 23 | if (image == FregeLabelProvider.VAR_IMAGE 24 | && (TSymbolT.vis(symbol) != TVisibility.Public 25 | || TQName.isLocal(TSymbolT.name(symbol)))) 26 | image = FregeLabelProvider.LOCAL_IMAGE; 27 | return image; 28 | } 29 | return FregeLabelProvider.OUTLINE_IMAGE; 30 | } 31 | 32 | @Override 33 | public String getLabel() { 34 | return Utilities.label(global, symbol); 35 | } 36 | 37 | @Override 38 | public TPosition getPosition() { 39 | return TSymbolT.pos(symbol); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/frege/imp/wizards/FregeModuleWizard.java: -------------------------------------------------------------------------------- 1 | package frege.imp.wizards; 2 | 3 | import org.eclipse.core.resources.IFile; 4 | import org.eclipse.jface.viewers.IStructuredSelection; 5 | import org.eclipse.ui.IWorkbench; 6 | import org.eclipse.ui.IWorkbenchPage; 7 | import org.eclipse.ui.IWorkbenchWindow; 8 | import org.eclipse.ui.PartInitException; 9 | import org.eclipse.ui.ide.IDE; 10 | import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; 11 | 12 | import frege.FregePlugin; 13 | 14 | public class FregeModuleWizard extends BasicNewResourceWizard { 15 | private NewFregeModuleWizardPage mainPage; 16 | 17 | @Override 18 | public void addPages() { 19 | mainPage = new NewFregeModuleWizardPage(getSelection()); 20 | mainPage.setTitle("Frege module"); 21 | mainPage.setDescription("Create a new Frege module."); 22 | addPage(mainPage); 23 | } 24 | 25 | @Override 26 | public void init(IWorkbench workbench, IStructuredSelection currentSelection) { 27 | super.init(workbench, currentSelection); 28 | setWindowTitle("New Frege module"); 29 | setNeedsProgressMonitor(true); 30 | } 31 | 32 | @Override 33 | public boolean performFinish() { 34 | IFile file = mainPage.createNewFile(); 35 | if (file == null) { 36 | return false; 37 | } 38 | 39 | selectAndReveal(file); 40 | 41 | // Open editor on new file. 42 | IWorkbenchWindow dw = getWorkbench().getActiveWorkbenchWindow(); 43 | try { 44 | if (dw != null) { 45 | IWorkbenchPage page = dw.getActivePage(); 46 | if (page != null) { 47 | IDE.openEditor(page, file, true); 48 | } 49 | } 50 | } catch (PartInitException e) { 51 | FregePlugin.getInstance().logException(e.getMessage(), e); 52 | } 53 | 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/frege/imp/wizards/FregeProjectWizard.java: -------------------------------------------------------------------------------- 1 | package frege.imp.wizards; 2 | 3 | import org.eclipse.core.runtime.CoreException; 4 | import org.eclipse.core.runtime.NullProgressMonitor; 5 | import org.eclipse.jdt.core.IJavaElement; 6 | import org.eclipse.jface.viewers.IStructuredSelection; 7 | import org.eclipse.ui.IWorkbench; 8 | import org.eclipse.ui.IWorkbenchPage; 9 | import org.eclipse.ui.IWorkbenchPart; 10 | import org.eclipse.ui.IWorkbenchWindow; 11 | import org.eclipse.ui.IWorkingSet; 12 | import org.eclipse.ui.PlatformUI; 13 | import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; 14 | 15 | import frege.FregePlugin; 16 | 17 | public class FregeProjectWizard extends BasicNewResourceWizard { 18 | private NewFregeProjectWizardPageOne firstPage; 19 | private NewFregeProjectWizardPageTwo secondPage; 20 | 21 | public FregeProjectWizard() { 22 | firstPage = new NewFregeProjectWizardPageOne(); 23 | firstPage.setTitle("Create a Frege project"); 24 | firstPage.setDescription("Create a Frege project in the workspace or in an external location."); 25 | 26 | secondPage = new NewFregeProjectWizardPageTwo(firstPage); 27 | secondPage.setTitle("Frege Settings"); 28 | secondPage.setDescription("Define the Frege build settings."); 29 | } 30 | 31 | private IWorkbenchPart getActivePart() { 32 | IWorkbenchWindow activeWindow = getWorkbench().getActiveWorkbenchWindow(); 33 | if (activeWindow != null) { 34 | IWorkbenchPage activePage = activeWindow.getActivePage(); 35 | if (activePage != null) { 36 | return activePage.getActivePart(); 37 | } 38 | } 39 | return null; 40 | } 41 | 42 | @Override 43 | public void addPages() { 44 | addPage(firstPage); 45 | addPage(secondPage); 46 | 47 | firstPage.init(getSelection(), getActivePart()); 48 | } 49 | 50 | @Override 51 | public boolean performFinish() { 52 | try { 53 | secondPage.performFinish(new NullProgressMonitor()); 54 | } catch (CoreException e) { 55 | FregePlugin.getInstance().logException(e.getMessage(), e); 56 | return false; 57 | } catch (InterruptedException e) { 58 | return false; 59 | } 60 | 61 | final IJavaElement newElement = secondPage.getJavaProject(); 62 | 63 | IWorkingSet[] workingSets = firstPage.getWorkingSets(); 64 | if (workingSets.length > 0) { 65 | PlatformUI.getWorkbench().getWorkingSetManager().addToWorkingSets(newElement, workingSets); 66 | } 67 | 68 | selectAndReveal(secondPage.getJavaProject().getProject()); 69 | return true; 70 | } 71 | 72 | @Override 73 | public void init(IWorkbench theWorkbench, IStructuredSelection currentSelection) { 74 | super.init(theWorkbench, currentSelection); 75 | setWindowTitle("New Frege Project"); 76 | } 77 | 78 | @Override 79 | public boolean performCancel() { 80 | secondPage.performCancel(); 81 | return super.performCancel(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/frege/imp/wizards/NewFregeModuleWizardPage.java: -------------------------------------------------------------------------------- 1 | package frege.imp.wizards; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.nio.charset.Charset; 6 | import java.util.Arrays; 7 | import java.util.Iterator; 8 | import java.util.Optional; 9 | import java.util.stream.Stream; 10 | 11 | import org.eclipse.core.resources.IContainer; 12 | import org.eclipse.core.resources.IFile; 13 | import org.eclipse.core.resources.IProject; 14 | import org.eclipse.core.resources.IResource; 15 | import org.eclipse.core.resources.ResourcesPlugin; 16 | import org.eclipse.core.runtime.Adapters; 17 | import org.eclipse.core.runtime.CoreException; 18 | import org.eclipse.core.runtime.IPath; 19 | import org.eclipse.core.runtime.IStatus; 20 | import org.eclipse.core.runtime.Path; 21 | import org.eclipse.core.runtime.Status; 22 | import org.eclipse.jdt.core.IClasspathEntry; 23 | import org.eclipse.jdt.core.IJavaProject; 24 | import org.eclipse.jdt.core.IPackageFragmentRoot; 25 | import org.eclipse.jdt.core.JavaCore; 26 | import org.eclipse.jdt.core.JavaModelException; 27 | import org.eclipse.jdt.ui.JavaElementComparator; 28 | import org.eclipse.jdt.ui.JavaElementLabelProvider; 29 | import org.eclipse.jdt.ui.StandardJavaElementContentProvider; 30 | import org.eclipse.jface.operation.IRunnableWithProgress; 31 | import org.eclipse.jface.viewers.IStructuredSelection; 32 | import org.eclipse.jface.viewers.Viewer; 33 | import org.eclipse.jface.viewers.ViewerFilter; 34 | import org.eclipse.jface.window.Window; 35 | import org.eclipse.jface.wizard.WizardPage; 36 | import org.eclipse.swt.SWT; 37 | import org.eclipse.swt.events.KeyAdapter; 38 | import org.eclipse.swt.events.KeyEvent; 39 | import org.eclipse.swt.events.SelectionAdapter; 40 | import org.eclipse.swt.events.SelectionEvent; 41 | import org.eclipse.swt.layout.GridData; 42 | import org.eclipse.swt.layout.GridLayout; 43 | import org.eclipse.swt.widgets.Button; 44 | import org.eclipse.swt.widgets.Composite; 45 | import org.eclipse.swt.widgets.Label; 46 | import org.eclipse.swt.widgets.Text; 47 | import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; 48 | import org.eclipse.ui.dialogs.ISelectionStatusValidator; 49 | import org.eclipse.ui.ide.undo.CreateFileOperation; 50 | import org.eclipse.ui.ide.undo.WorkspaceUndoUtil; 51 | 52 | import frege.FregePlugin; 53 | 54 | public class NewFregeModuleWizardPage extends WizardPage { 55 | private IStructuredSelection currentSelection; 56 | private IContainer sourceFolder; 57 | private String moduleName; 58 | private String moduleSimpleName; 59 | private IPath modulePath; 60 | 61 | private IFile newFile; 62 | private Text textSourceFolder; 63 | private Text textName; 64 | 65 | public NewFregeModuleWizardPage(IStructuredSelection selection) { 66 | super("NewFregeModuleWizardPage"); 67 | this.currentSelection = selection; 68 | } 69 | 70 | @Override 71 | public void createControl(Composite parent) { 72 | initializeDialogUnits(parent); 73 | 74 | Composite topLevel = new Composite(parent, SWT.NONE); 75 | GridLayout topLevelLayout = new GridLayout(); 76 | topLevelLayout.numColumns = 3; 77 | topLevel.setLayout(topLevelLayout); 78 | topLevel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL)); 79 | topLevel.setFont(parent.getFont()); 80 | 81 | Label lbSourceFolder = new Label(topLevel, SWT.NONE); 82 | lbSourceFolder.setFont(topLevel.getFont()); 83 | lbSourceFolder.setText("Source Folder:"); 84 | 85 | textSourceFolder = new Text(topLevel, SWT.BORDER); 86 | textSourceFolder.setFont(topLevel.getFont()); 87 | textSourceFolder.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); 88 | textSourceFolder.addKeyListener(new KeyAdapter() { 89 | @Override 90 | public void keyReleased(KeyEvent e) { 91 | if (e.keyCode != SWT.CR) 92 | setSourceFolder(textSourceFolder.getText()); 93 | } 94 | }); 95 | 96 | Button btnSourceFolderBrowse = new Button(topLevel, SWT.PUSH); 97 | btnSourceFolderBrowse.setFont(topLevel.getFont()); 98 | btnSourceFolderBrowse.setText("Browse..."); 99 | btnSourceFolderBrowse.addSelectionListener(new SelectionAdapter() { 100 | @Override 101 | public void widgetSelected(SelectionEvent e) { 102 | ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), 103 | new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT), 104 | new StandardJavaElementContentProvider()); 105 | dialog.setValidator(new ISelectionStatusValidator() { 106 | @Override 107 | public IStatus validate(Object[] selection) { 108 | if (selection.length != 1) 109 | return new Status(IStatus.ERROR, FregePlugin.getInstance().getID(), ""); 110 | Object selectedObject = selection[0]; 111 | try { 112 | if (selectedObject instanceof IPackageFragmentRoot 113 | && ((IPackageFragmentRoot) selectedObject).getKind() == IPackageFragmentRoot.K_SOURCE) 114 | return new Status(IStatus.OK, FregePlugin.getInstance().getID(), ""); 115 | else 116 | return new Status(IStatus.ERROR, FregePlugin.getInstance().getID(), ""); 117 | } catch (JavaModelException e) { 118 | return new Status(IStatus.ERROR, FregePlugin.getInstance().getID(), e.getMessage(), e); 119 | } 120 | } 121 | }); 122 | dialog.setComparator(new JavaElementComparator()); 123 | dialog.setTitle("Source Folder Selection"); 124 | dialog.setMessage("Choose a source folder:"); 125 | dialog.addFilter(new ViewerFilter() { 126 | @Override 127 | public boolean select(Viewer viewer, Object parentElement, Object element) { 128 | try { 129 | if (element instanceof IPackageFragmentRoot) 130 | return ((IPackageFragmentRoot) element).getKind() == IPackageFragmentRoot.K_SOURCE; 131 | else if (element instanceof IJavaProject) 132 | return true; 133 | else 134 | return false; 135 | } catch (JavaModelException e) { 136 | return false; 137 | } 138 | } 139 | }); 140 | dialog.setInput(JavaCore.create(ResourcesPlugin.getWorkspace().getRoot())); 141 | dialog.setHelpAvailable(false); 142 | dialog.setAllowMultiple(false); 143 | if (dialog.open() == Window.OK) { 144 | IPackageFragmentRoot sourcePackage = ((IPackageFragmentRoot) dialog.getFirstResult()); 145 | setSourceFolder(sourcePackage.getJavaProject().getProject() 146 | .getFolder(sourcePackage.getPath().removeFirstSegments(1))); 147 | } 148 | } 149 | }); 150 | 151 | Label lbName = new Label(topLevel, SWT.NONE); 152 | lbName.setFont(topLevel.getFont()); 153 | lbName.setText("Name:"); 154 | 155 | textName = new Text(topLevel, SWT.BORDER); 156 | textName.setFont(topLevel.getFont()); 157 | textName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); 158 | textName.addKeyListener(new KeyAdapter() { 159 | @Override 160 | public void keyReleased(KeyEvent e) { 161 | if (e.keyCode != SWT.CR) 162 | setModuleName(textName.getText(), false); 163 | } 164 | }); 165 | 166 | if (currentSelection != null) { 167 | Iterator it = currentSelection.iterator(); 168 | if (it.hasNext()) { 169 | Object object = it.next(); 170 | IResource selectedResource = Adapters.adapt(object, IResource.class); 171 | if (selectedResource != null) { 172 | IProject project = selectedResource.getProject(); 173 | getSourceDirs(project).map(path -> { 174 | if (path.equals(project.getFullPath())) { 175 | return project; 176 | } else { 177 | return ResourcesPlugin.getWorkspace().getRoot().getFolder(path); 178 | } 179 | }).findFirst().ifPresent(this::setSourceFolder); 180 | IPath path = selectedResource.getFullPath(); 181 | IPath moduleNamePath = getSourceDirs(project).filter(srcDir -> srcDir.isPrefixOf(path)) 182 | .map(srcDir -> path.removeFirstSegments(srcDir.segmentCount())).map(filePath -> { 183 | if (selectedResource.getType() == IResource.FILE) 184 | return filePath.removeLastSegments(1); 185 | else 186 | return filePath; 187 | }).findFirst().orElse(Path.EMPTY); 188 | String moduleName = makeModuleName(moduleNamePath); 189 | setModuleName(moduleName.isEmpty() ? "" : moduleName + "."); 190 | } 191 | } 192 | } 193 | 194 | setErrorMessage(null); 195 | setMessage(null); 196 | setControl(topLevel); 197 | } 198 | 199 | public IFile createNewFile() { 200 | if (newFile != null) 201 | return newFile; 202 | IFile newFile = sourceFolder.getFile(modulePath); 203 | 204 | IRunnableWithProgress op = monitor -> { 205 | // @formatter:off 206 | String contents = 207 | "module " + moduleName + " where\n" + 208 | "\n" + 209 | "data " + moduleSimpleName + " = " + moduleSimpleName + "\n"; 210 | // @formatter:on 211 | try { 212 | Charset charset = Charset.forName(sourceFolder.getDefaultCharset()); 213 | CreateFileOperation op1 = new CreateFileOperation(newFile, null, 214 | new ByteArrayInputStream(contents.getBytes(charset)), "NewFile"); 215 | op1.execute(monitor, WorkspaceUndoUtil.getUIInfoAdapter(getShell())); 216 | } catch (Exception e) { 217 | FregePlugin.getInstance().logException(e.getMessage(), e); 218 | } 219 | }; 220 | try { 221 | getContainer().run(true, true, op); 222 | } catch (InterruptedException e) { 223 | return null; 224 | } catch (InvocationTargetException e) { 225 | FregePlugin.getInstance().logException(e.getMessage(), e); 226 | return null; 227 | } 228 | this.newFile = newFile; 229 | return newFile; 230 | } 231 | 232 | private Stream getSourceDirs(IProject project) { 233 | try { 234 | if (project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) { 235 | IJavaProject javaProject = JavaCore.create(project); 236 | return Arrays.stream(javaProject.getResolvedClasspath(true)) 237 | .filter(entry -> entry.getContentKind() == IPackageFragmentRoot.K_SOURCE) 238 | .map(IClasspathEntry::getPath); 239 | } 240 | } catch (CoreException e) { 241 | FregePlugin.getInstance().logException(e.getMessage(), e); 242 | } 243 | return Stream.empty(); 244 | } 245 | 246 | private void setSourceFolder(String sourceFolder) { 247 | if (!Path.isValidPosixPath(sourceFolder)) { 248 | setErrorMessage("Invalid source folder path"); 249 | return; 250 | } 251 | IPath path = Path.forPosix(sourceFolder); 252 | IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path, false); 253 | if (resource == null) { 254 | setErrorMessage("Folder does not exists"); 255 | return; 256 | } 257 | if (!(resource instanceof IContainer)) { 258 | setErrorMessage("Folder does not exists"); 259 | return; 260 | } 261 | setSourceFolder((IContainer) resource, false); 262 | } 263 | 264 | private void setSourceFolder(IContainer sourceFolder) { 265 | setSourceFolder(sourceFolder, true); 266 | } 267 | 268 | private void setSourceFolder(IContainer sourceFolder, boolean updateText) { 269 | this.sourceFolder = sourceFolder; 270 | if (updateText) 271 | textSourceFolder.setText(sourceFolder.getFullPath().makeRelative().toString()); 272 | setModuleName(textName.getText(), false); 273 | } 274 | 275 | private String makeModuleName(IPath modulePath) { 276 | return String.join(".", modulePath.segments()); 277 | } 278 | 279 | private boolean isValidIdentifier(String name) { 280 | if (name.isEmpty()) 281 | return false; 282 | if (!Character.isJavaIdentifierStart(name.charAt(0))) 283 | return false; 284 | for (int i = 1; i < name.length(); ++i) 285 | if (!Character.isJavaIdentifierPart(name.charAt(i))) 286 | return false; 287 | return true; 288 | } 289 | 290 | private boolean isValidModuleName(String moduleName) { 291 | if (moduleName.startsWith(".") || moduleName.endsWith(".")) 292 | return false; 293 | String[] identifiers = moduleName.split("\\."); 294 | return Arrays.stream(identifiers).allMatch(this::isValidIdentifier) 295 | && Character.isUpperCase(identifiers[identifiers.length - 1].charAt(0)); 296 | } 297 | 298 | private Optional parseModuleName(String moduleName) { 299 | if (!isValidModuleName(moduleName)) 300 | return Optional.empty(); 301 | String pathString = moduleName.replace('.', '/'); 302 | if (!Path.isValidPosixPath(pathString)) 303 | return Optional.empty(); 304 | return Optional.of(Path.forPosix(pathString)); 305 | } 306 | 307 | private void setModuleName(String moduleName) { 308 | setModuleName(moduleName, true); 309 | } 310 | 311 | private void setModuleName(String moduleName, boolean updateText) { 312 | this.moduleName = null; 313 | this.moduleSimpleName = null; 314 | this.modulePath = null; 315 | try { 316 | if (updateText) 317 | textName.setText(moduleName); 318 | if (sourceFolder != null) { 319 | if (moduleName.isEmpty()) { 320 | setErrorMessage("Empty module name"); 321 | return; 322 | } 323 | Optional modulePathO = parseModuleName(moduleName); 324 | if (!modulePathO.isPresent()) { 325 | setErrorMessage("Invalid module name"); 326 | return; 327 | } 328 | IPath moduleNamePath = modulePathO.get(); 329 | if (sourceFolder.exists(moduleNamePath)) { 330 | setErrorMessage("Module already exists"); 331 | return; 332 | } 333 | this.moduleName = moduleName; 334 | this.moduleSimpleName = moduleNamePath.segments()[moduleNamePath.segmentCount() - 1]; 335 | this.modulePath = moduleNamePath.addFileExtension("fr"); 336 | setErrorMessage(null); 337 | } 338 | } finally { 339 | setPageComplete(this.modulePath != null); 340 | } 341 | } 342 | } 343 | -------------------------------------------------------------------------------- /src/frege/imp/wizards/NewFregeProjectWizardPageOne.java: -------------------------------------------------------------------------------- 1 | package frege.imp.wizards; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Stream; 5 | 6 | import org.eclipse.core.runtime.Path; 7 | import org.eclipse.jdt.core.IClasspathEntry; 8 | import org.eclipse.jdt.core.JavaCore; 9 | import org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageOne; 10 | 11 | import frege.FregePlugin; 12 | 13 | public class NewFregeProjectWizardPageOne extends NewJavaProjectWizardPageOne { 14 | @Override 15 | public IClasspathEntry[] getDefaultClasspathEntries() { 16 | return Stream 17 | .concat(Arrays.stream(super.getDefaultClasspathEntries()), 18 | Stream.of(JavaCore.newLibraryEntry(new Path(FregePlugin.fregeLib), null, null))) 19 | .toArray(IClasspathEntry[]::new); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/frege/imp/wizards/NewFregeProjectWizardPageTwo.java: -------------------------------------------------------------------------------- 1 | package frege.imp.wizards; 2 | 3 | import org.eclipse.core.resources.IProject; 4 | import org.eclipse.core.runtime.CoreException; 5 | import org.eclipse.core.runtime.IProgressMonitor; 6 | import org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageOne; 7 | import org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo; 8 | 9 | import frege.imp.builders.FregeNature; 10 | 11 | public class NewFregeProjectWizardPageTwo extends NewJavaProjectWizardPageTwo { 12 | public NewFregeProjectWizardPageTwo(NewJavaProjectWizardPageOne mainPage) { 13 | super(mainPage); 14 | } 15 | 16 | @Override 17 | public void configureJavaProject(String newProjectCompliance, IProgressMonitor monitor) 18 | throws CoreException, InterruptedException { 19 | super.configureJavaProject(newProjectCompliance, monitor); 20 | 21 | IProject project = getJavaProject().getProject(); 22 | 23 | if (!project.hasNature(FregeNature.k_natureID)) { 24 | new FregeNature().addToProject(project); 25 | } 26 | } 27 | } 28 | --------------------------------------------------------------------------------