1 package org.simantics.scl.ui.editor2;
4 import org.eclipse.core.commands.AbstractHandler;
5 import org.eclipse.core.commands.ExecutionEvent;
6 import org.eclipse.core.commands.ExecutionException;
7 import org.eclipse.swt.custom.StyledText;
8 import org.eclipse.swt.widgets.Control;
9 import org.eclipse.ui.IEditorPart;
10 import org.eclipse.ui.PlatformUI;
11 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
12 import org.simantics.scl.compiler.errors.Locations;
13 import org.simantics.scl.compiler.module.InvalidModulePathException;
14 import org.simantics.scl.compiler.module.ModuleUtils;
15 import org.simantics.scl.compiler.source.ModuleSource;
16 import org.simantics.scl.osgi.SCLOsgi;
17 import org.simantics.scl.ui.editor.completion.SCLTextEditorEnvironment;
19 public class OpenDeclaration extends AbstractHandler {
21 private static boolean isIdentifierPart(char c) {
22 return Character.isJavaIdentifierPart(c) || c=='.';
25 private static String extractIdentifierAt(String text, int caretPos) {
26 int startPos = caretPos;
27 while(startPos > 0 && isIdentifierPart(text.charAt(startPos-1)))
29 int endPos = caretPos;
30 while(endPos < text.length() && isIdentifierPart(text.charAt(endPos)))
32 return text.substring(startPos, endPos);
35 private static final String SYMBOL_CHARS = "!$%&*+/<=>?@\\^|-:~.";
37 private static boolean isSymbolPart(char c) {
38 for(int i=0;i<SYMBOL_CHARS.length();++i)
39 if(SYMBOL_CHARS.charAt(i) == c)
44 private static String extractSymbolAt(String text, int caretPos) {
45 int startPos = caretPos;
46 while(startPos > 0 && isSymbolPart(text.charAt(startPos-1)))
48 int endPos = caretPos;
49 while(endPos < text.length() && isSymbolPart(text.charAt(endPos)))
51 return text.substring(startPos, endPos);
54 public static String extractIdentifierOrSymbolAt(String text, int caretPos) {
55 String result = extractIdentifierAt(text, caretPos);
58 return extractSymbolAt(text, caretPos);
61 private static String extractLineAt(String text, int caretPos) {
62 int startPos = caretPos;
63 while(startPos > 0 && !isNewline(text.charAt(startPos-1)))
65 int endPos = caretPos;
66 while(endPos < text.length() && !isNewline(text.charAt(endPos)))
68 return text.substring(startPos, endPos);
71 private static boolean isNewline(char c) {
72 return c=='\n' || c=='\r';
76 public Object execute(ExecutionEvent event) throws ExecutionException {
78 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
79 if(!(editor instanceof SCLModuleEditor2))
81 SCLModuleEditor2 moduleEditor = (SCLModuleEditor2)editor;
82 StyledText styledText = (StyledText)moduleEditor.getAdapter(Control.class);
83 String text = styledText.getText();
84 int caretOffset = styledText.getCaretOffset();
86 // Find the line where the caret is
87 String lineAtCaret = extractLineAt(text, caretOffset);
88 if(lineAtCaret.startsWith("import ") || lineAtCaret.startsWith("include ")) {
89 int p1 = lineAtCaret.indexOf('"', 6);
90 int p2 = lineAtCaret.indexOf('"', p1+1);
91 SCLModuleEditorInput input = (SCLModuleEditorInput)moduleEditor.getEditorInput();
93 String moduleName = ModuleUtils.resolveAbsolutePath(input.getModuleName(), lineAtCaret.substring(p1+1, p2));
94 ModuleSource source = SCLOsgi.SOURCE_REPOSITORY.getModuleSource(moduleName, null);
96 OpenSCLModule.openModule(moduleName);
98 } catch (InvalidModulePathException e) {
103 // Try to find an identifier at caret
104 String identifierAtCaret = extractIdentifierOrSymbolAt(text, caretOffset);
105 if(identifierAtCaret.isEmpty())
107 SCLTextEditorEnvironment editorEnvironment = moduleEditor.getSCLTextEditorEnvironment();
108 editorEnvironment.updateEnvironment(moduleEditor.getDocument());
109 SCLValue value = editorEnvironment.getValue(identifierAtCaret);
110 System.out.println("identifierAtCaret = " + identifierAtCaret + " [" + Locations.beginOf(value.definitionLocation) + ", " + Locations.endOf(value.definitionLocation) + "]");
112 OpenSCLDefinition.openDefinition(value);