(refs #7386) Minor SCL tools improvements
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / editor2 / OpenDeclaration.java
1 package org.simantics.scl.ui.editor2;
2
3
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;
18
19 public class OpenDeclaration extends AbstractHandler {
20
21     private static boolean isIdentifierPart(char c) {
22         return Character.isJavaIdentifierPart(c) || c=='.';
23     }
24     
25     private static String extractIdentifierAt(String text, int caretPos) {
26         int startPos = caretPos;
27         while(startPos > 0 && isIdentifierPart(text.charAt(startPos-1)))
28             --startPos;
29         int endPos = caretPos;
30         while(endPos < text.length() && isIdentifierPart(text.charAt(endPos)))
31             ++endPos;
32         return text.substring(startPos, endPos);
33     }
34     
35     private static final String SYMBOL_CHARS = "!$%&*+/<=>?@\\^|-:~.";
36     
37     private static boolean isSymbolPart(char c) {
38         for(int i=0;i<SYMBOL_CHARS.length();++i)
39             if(SYMBOL_CHARS.charAt(i) == c)
40                 return true;
41         return false;
42     }
43     
44     private static String extractSymbolAt(String text, int caretPos) {
45         int startPos = caretPos;
46         while(startPos > 0 && isSymbolPart(text.charAt(startPos-1)))
47             --startPos;
48         int endPos = caretPos;
49         while(endPos < text.length() && isSymbolPart(text.charAt(endPos)))
50             ++endPos;
51         return text.substring(startPos, endPos);
52     }
53     
54     public static String extractIdentifierOrSymbolAt(String text, int caretPos) {
55         String result = extractIdentifierAt(text, caretPos);
56         if(!result.isEmpty())
57             return result;
58         return extractSymbolAt(text, caretPos);
59     }
60     
61     private static String extractLineAt(String text, int caretPos) {
62         int startPos = caretPos;
63         while(startPos > 0 && !isNewline(text.charAt(startPos-1)))
64             --startPos;
65         int endPos = caretPos;
66         while(endPos < text.length() && !isNewline(text.charAt(endPos)))
67             ++endPos;
68         return text.substring(startPos, endPos);
69     }
70     
71     private static boolean isNewline(char c) {
72         return c=='\n' || c=='\r';
73     }
74
75     @Override
76     public Object execute(ExecutionEvent event) throws ExecutionException {
77         IEditorPart editor = 
78                 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
79         if(!(editor instanceof SCLModuleEditor2))
80             return null;
81         SCLModuleEditor2 moduleEditor = (SCLModuleEditor2)editor;
82         StyledText styledText = (StyledText)moduleEditor.getAdapter(Control.class);
83         String text = styledText.getText();
84         int caretOffset = styledText.getCaretOffset();
85         
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();
92             try {
93                     String moduleName = ModuleUtils.resolveAbsolutePath(input.getModuleName(), lineAtCaret.substring(p1+1, p2));
94                 ModuleSource source = SCLOsgi.SOURCE_REPOSITORY.getModuleSource(moduleName, null);
95                 if (source != null) {
96                         OpenSCLModule.openModule(moduleName);
97                 }
98             } catch (InvalidModulePathException e) {
99                 // Nothing to do
100             }
101         }
102         else {
103             // Try to find an identifier at caret
104             String identifierAtCaret = extractIdentifierOrSymbolAt(text, caretOffset);
105             if(identifierAtCaret.isEmpty())
106                 return null;
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) + "]");
111             if(value != null)
112                 OpenSCLDefinition.openDefinition(value);
113         }
114         return null;
115     }
116
117 }