4b6818ab7b805587bfe6306a9f1154e48ac0e3ad
[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.module.InvalidModulePathException;
13 import org.simantics.scl.compiler.module.ModuleUtils;
14 import org.simantics.scl.compiler.source.ModuleSource;
15 import org.simantics.scl.osgi.SCLOsgi;
16 import org.simantics.scl.ui.editor.completion.SCLTextEditorEnvironment;
17
18 public class OpenDeclaration extends AbstractHandler {
19
20     private static boolean isIdentifierPart(char c) {
21         return Character.isJavaIdentifierPart(c) || c=='.';
22     }
23     
24     private static String extractIdentifierAt(String text, int caretPos) {
25         int startPos = caretPos;
26         while(startPos > 0 && isIdentifierPart(text.charAt(startPos-1)))
27             --startPos;
28         int endPos = caretPos;
29         while(endPos < text.length() && isIdentifierPart(text.charAt(endPos)))
30             ++endPos;
31         return text.substring(startPos, endPos);
32     }
33     
34     private static final String SYMBOL_CHARS = "!$%&*+/<=>?@\\^|-:~.";
35     
36     private static boolean isSymbolPart(char c) {
37         for(int i=0;i<SYMBOL_CHARS.length();++i)
38             if(SYMBOL_CHARS.charAt(i) == c)
39                 return true;
40         return false;
41     }
42     
43     private static String extractSymbolAt(String text, int caretPos) {
44         int startPos = caretPos;
45         while(startPos > 0 && isSymbolPart(text.charAt(startPos-1)))
46             --startPos;
47         int endPos = caretPos;
48         while(endPos < text.length() && isSymbolPart(text.charAt(endPos)))
49             ++endPos;
50         return text.substring(startPos, endPos);
51     }
52     
53     public static String extractIdentifierOrSymbolAt(String text, int caretPos) {
54         String result = extractIdentifierAt(text, caretPos);
55         if(!result.isEmpty())
56             return result;
57         return extractSymbolAt(text, caretPos);
58     }
59     
60     private static String extractLineAt(String text, int caretPos) {
61         int startPos = caretPos;
62         while(startPos > 0 && !isNewline(text.charAt(startPos-1)))
63             --startPos;
64         int endPos = caretPos;
65         while(endPos < text.length() && !isNewline(text.charAt(endPos)))
66             ++endPos;
67         return text.substring(startPos, endPos);
68     }
69     
70     private static boolean isNewline(char c) {
71         return c=='\n' || c=='\r';
72     }
73
74     @Override
75     public Object execute(ExecutionEvent event) throws ExecutionException {
76         IEditorPart editor = 
77                 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
78         if(!(editor instanceof SCLModuleEditor2))
79             return null;
80         SCLModuleEditor2 moduleEditor = (SCLModuleEditor2)editor;
81         StyledText styledText = (StyledText)moduleEditor.getAdapter(Control.class);
82         String text = styledText.getText();
83         int caretOffset = styledText.getCaretOffset();
84         
85         // Find the line where the caret is
86         String lineAtCaret = extractLineAt(text, caretOffset);
87         if(lineAtCaret.startsWith("import ") || lineAtCaret.startsWith("include ")) {
88             int p1 = lineAtCaret.indexOf('"', 6);
89             int p2 = lineAtCaret.indexOf('"', p1+1);
90             SCLModuleEditorInput input = (SCLModuleEditorInput)moduleEditor.getEditorInput();
91             try {
92                     String moduleName = ModuleUtils.resolveAbsolutePath(input.getModuleName(), lineAtCaret.substring(p1+1, p2));
93                 ModuleSource source = SCLOsgi.SOURCE_REPOSITORY.getModuleSource(moduleName, null);
94                 if (source != null) {
95                         OpenSCLModule.openModule(moduleName);
96                 }
97             } catch (InvalidModulePathException e) {
98                 // Nothing to do
99             }
100         }
101         else {
102             // Try to find an identifier at caret
103             String identifierAtCaret = extractIdentifierOrSymbolAt(text, caretOffset);
104             if(identifierAtCaret.isEmpty())
105                 return null;
106             SCLTextEditorEnvironment editorEnvironment = moduleEditor.getSCLTextEditorEnvironment();
107             editorEnvironment.updateEnvironment(moduleEditor.getDocument());
108             SCLValue value = editorEnvironment.getValue(identifierAtCaret);
109             if(value != null)
110                 OpenSCLDefinition.openDefinition(value);
111         }
112         return null;
113     }
114
115 }