Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Patches contributed by Thomas Fletcher:

* new Outline doing partial updates if possible
* It provides both alphabetical and file ordered based sorting
* Added support for background document synchronizing so that as we expand beyond functions we can better handle incremental changes (or use the AST for 2.0)
* Added new icons for the Outline
* Added a static logging method to the plugin.  
* Added in several fixes to NPE
  • Loading branch information...
commit dbcfd96f6ca3269ff645fa897d25d668f9d0ba67 1 parent 09b6010
jasonsantos authored
View
2  org.keplerproject.ldt.core/src/org/keplerproject/ldt/core/LuaCorePlugin.java
@@ -33,7 +33,9 @@
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
import org.keplerproject.ldt.core.project.LuaProjectNature;
import org.osgi.framework.BundleContext;
View
2  org.keplerproject.ldt.core/src/org/keplerproject/ldt/core/compiler/LuaResourceDeltaVisitor.java
@@ -30,12 +30,12 @@
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
import org.keplerproject.ldt.core.ILuaEntry;
import org.keplerproject.ldt.core.LuaProject;
import org.keplerproject.ldt.core.LuaScriptsSpecs;
import org.keplerproject.ldt.core.luadoc.LuadocGenerator;
import org.keplerproject.luajava.LuaState;
-import org.keplerproject.luajava.LuaStateFactory;
/**
* The Lua Code DeltaVisitor remade to fit Lua 5.1 API
View
9 org.keplerproject.ldt.core/src/org/keplerproject/ldt/core/lua/modules/LuaModuleLoader.java
@@ -21,6 +21,7 @@
import java.io.IOException;
import java.net.URL;
+import org.keplerproject.ldt.core.LuaCorePlugin;
import org.keplerproject.ldt.core.utils.ResourceUtils;
import org.keplerproject.luajava.JavaFunction;
import org.keplerproject.luajava.LuaException;
@@ -53,6 +54,13 @@ private static String dumpTable(LuaState L) {
return sb.toString();
}
+ /**
+ * Attempt to load the file specified by the URL
+ * @param L The lua state to use for the loader
+ * @param u The URL to load
+ * @return 0 if there are no errors loading the string
+ * @throws IOException If there is a problem acessing the URL content
+ */
private static int LoadFile(LuaState L, URL u) throws IOException {
int res = -1;
@@ -61,6 +69,7 @@ private static int LoadFile(LuaState L, URL u) throws IOException {
res = L.LloadString(body);
}
+
return res;
}
View
BIN  org.keplerproject.ldt.ui/icons/lua_function.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  org.keplerproject.ldt.ui/icons/sort.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
2  org.keplerproject.ldt.ui/src/org/keplerproject/ldt/ui/editors/LuaEditor.java
@@ -238,7 +238,7 @@ public String getInstanceId() {
public LuaOutlinePage getContentOutline() {
if (luaOutlinePage == null ) {
luaOutlinePage = new LuaOutlinePage(getDocumentProvider(), this);
- luaOutlinePage.setInput((IEditorInput) this);
+ luaOutlinePage.setInput(this);
}
return luaOutlinePage;
View
134 org.keplerproject.ldt.ui/src/org/keplerproject/ldt/ui/editors/LuaOutlinePage.java
@@ -1,42 +1,138 @@
package org.keplerproject.ldt.ui.editors;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.keplerproject.ldt.ui.LDTUIPlugin;
import org.keplerproject.ldt.ui.editors.outline.LuaOutlineContentProvider;
import org.keplerproject.ldt.ui.editors.outline.LuaOutlineLabelProvider;
+import org.keplerproject.ldt.ui.editors.outline.LuaOutlineContentProvider.FunctionDefinition;
-public class LuaOutlinePage extends ContentOutlinePage implements
- IContentOutlinePage {
+public class LuaOutlinePage extends ContentOutlinePage implements IContentOutlinePage {
- IEditorInput in;
+ LuaEditor fTargetEditor;
+
+ IAction fSortByName;
+
+ /**
+ * Provide a viewer comparator that sorts items based on their offset
+ * locations in the document. This allows items to be listed in their
+ * order of appearance in the file.
+ */
+ class DocumentOffsetComparator extends ViewerComparator {
+ public int compare(Viewer viewer, Object arg0, Object arg1) {
+ if(!(arg0 instanceof FunctionDefinition) || !(arg1 instanceof FunctionDefinition)) {
+ return super.compare(viewer, arg0, arg1);
+ }
+ FunctionDefinition fd0 = (FunctionDefinition)arg0;
+ FunctionDefinition fd1 = (FunctionDefinition)arg1;
+ return fd0.getCharacterOffset() - fd1.getCharacterOffset();
+ }
+
+ public boolean isSorterProperty(Object element, String property) {
+ if(LuaOutlineContentProvider.OFFSET_PROPERTY.equals(property)) {
+ return true;
+ }
+ return false;
+ }
+ }
- public LuaOutlinePage(IDocumentProvider documentProvider,
- LuaEditor luaEditor) {
+ public LuaOutlinePage(IDocumentProvider documentProvider, LuaEditor luaEditor) {
super();
+ setInput(luaEditor);
}
- public void setInput(IEditorInput editorInput) {
- in = editorInput;
- System.out.println("setInput");
+ public void setInput(LuaEditor luaEditor) {
+ fTargetEditor = (LuaEditor)luaEditor;
+
+ TreeViewer viewer = getTreeViewer();
+ if(viewer != null) {
+ viewer.setInput(fTargetEditor);
+ }
+ }
+
+ public void createControl(Composite parent) {
+ createActions();
+
+ super.createControl(parent);
+
+ TreeViewer viewer = getTreeViewer();
+
+ viewer.setLabelProvider(new LuaOutlineLabelProvider());
+ viewer.setContentProvider(new LuaOutlineContentProvider());
+ viewer.setInput(fTargetEditor);
+
+ viewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ setEditorPosition();
+ }
+ });
+
+ addActions();
+ updateSortingStyle();
}
- private void sysout(String name) {
- // TODO Auto-generated method stub
+ protected void createActions() {
+ String SORT_ICON_PATH = "icons/sort.gif";
+ fSortByName = new Action("Sort") {
+ public void run() {
+ updateSortingStyle();
+ }
+ };
+ fSortByName.setChecked(false);
+ fSortByName.setImageDescriptor(LDTUIPlugin.getImageDescriptor(SORT_ICON_PATH));
+ }
+
+ protected void addActions() {
+ IToolBarManager manager = getSite().getActionBars().getToolBarManager();
+ manager.add(fSortByName);
}
- public void createControl(Composite parent) {
- super.createControl(parent);
- TreeViewer viewer= getTreeViewer();
- viewer.setContentProvider(new LuaOutlineContentProvider());
- viewer.setLabelProvider(new LuaOutlineLabelProvider());
- viewer.addSelectionChangedListener(this);
- viewer.setInput(in);
- }
+ protected void updateSortingStyle() {
+ TreeViewer viewer = getTreeViewer();
+ if(viewer == null) {
+ return;
+ }
+ if(fSortByName.isChecked()) {
+ viewer.setComparator(new ViewerComparator());
+ } else {
+ viewer.setComparator(new DocumentOffsetComparator());
+ }
+ }
-}
+ protected void setEditorPosition() {
+ IStructuredSelection ss = (IStructuredSelection)getSelection();
+ if(ss == null || ss.isEmpty()) {
+ return;
+ }
+
+ Object item = ss.getFirstElement();
+ if(!(item instanceof FunctionDefinition)) {
+ return;
+ }
+
+ FunctionDefinition fd = (FunctionDefinition)item;
+ TextSelection ts = new TextSelection(fd.getCharacterOffset(),
+ fd.getCharacterEndOffset() - fd.getCharacterOffset());
+
+ ISelectionProvider provider = fTargetEditor.getSelectionProvider();
+ if(provider != null) {
+ provider.setSelection(ts);
+ }
+ }
+}
View
228 org.keplerproject.ldt.ui/src/org/keplerproject/ldt/ui/editors/outline/LuaOutlineContentProvider.java
@@ -1,39 +1,237 @@
package org.keplerproject.ldt.ui.editors.outline;
-import org.eclipse.jface.viewers.IContentProvider;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.keplerproject.ldt.ui.editors.LuaEditor;
+
+//Do this for the whole class until a compliance level is committed to
+@SuppressWarnings("unchecked")
public class LuaOutlineContentProvider implements ITreeContentProvider {
+ public static String OFFSET_PROPERTY = "offsets";
- private Object newInput = null;
- public void dispose() {
- }
+ StructuredViewer fViewer = null;
+ LuaEditor fEditorInput = null;
+
+ IDocument fDocument;
+ IDocumentListener fDocumentListener;
+
+ //Maintain a map of function name -> FunctionDefinition
+ //Use this to do incremental updates of only the differences in editing
+ HashMap fFunctionCache = new HashMap();
+
+ //TODO: Extract this to an external class
+ public static final class FunctionDefinition {
+ String fName;
+ int fCharOffset;
+ int fCharEndOffset;
+
+ public FunctionDefinition(String name, int charOffset, int charEndOffset) {
+ fName = name;
+ fCharOffset = charOffset;
+ fCharEndOffset = charEndOffset;
+ }
+
+ public String getName() {
+ return fName;
+ }
+ public int getCharacterOffset() {
+ return fCharOffset;
+ }
+
+ public void setCharacterOffset(int offset) {
+ fCharOffset = offset;
+ }
+
+ public int getCharacterEndOffset() {
+ return fCharEndOffset;
+ }
+
+ public void setCharacterEndOffset(int offset) {
+ fCharEndOffset = offset;
+ }
+
+ public String toString() {
+ return getName();
+ }
+
+ public boolean offsetsMatch(FunctionDefinition def) {
+ if(getCharacterOffset() != def.getCharacterOffset()) {
+ return false;
+ }
+ if(getCharacterEndOffset() != def.getCharacterEndOffset()) {
+ return false;
+ }
+ return true;
+ }
+ };
+
+ public LuaOutlineContentProvider() {
+ fDocumentListener = new IDocumentListener() {
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ }
+
+ public void documentChanged(DocumentEvent event) {
+ refreshCache(true);
+ }
+ };
+ }
+
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- // TODO Auto-generated method stub
- this.newInput = newInput;
- System.out.println((oldInput != null) ? oldInput.toString() : "null" + '>'+ newInput.toString());
+ if(fEditorInput != null) {
+ if(fDocument != null) {
+ fDocument.removeDocumentListener(fDocumentListener);
+ }
+ }
+
+ fViewer = null;
+ fEditorInput = null;
+ fDocument = null;
+ fFunctionCache.clear();
+
+ if(newInput instanceof LuaEditor) {
+ fViewer = (StructuredViewer)viewer;
+ fEditorInput = (LuaEditor)newInput;
+ IDocumentProvider provider = fEditorInput.getDocumentProvider();
+ fDocument = provider.getDocument(fEditorInput.getEditorInput());
+ if(fDocument != null) {
+ fDocument.addDocumentListener(fDocumentListener);
+ }
+ refreshCache(false);
+ }
}
+ public Object[] getElements(Object inputElement) {
+ if(inputElement == fEditorInput && fDocument != null) {
+ return fFunctionCache.values().toArray();
+ }
+
+ return new Object[0];
+ }
+
public Object[] getChildren(Object parentElement) {
- // TODO Auto-generated method stub
- return null;
+ return getElements(parentElement);
}
public Object getParent(Object element) {
- // TODO Auto-generated method stub
return null;
}
public boolean hasChildren(Object element) {
- // TODO Auto-generated method stub
- return false;
+ return getElements(element).length > 0;
}
- public Object[] getElements(Object inputElement) {
- // TODO Auto-generated method stub
- return new Object[0];
+ public void dispose() {
+ }
+
+ protected void refreshCache(boolean doRefresh) {
+ //TODO: Put in a background refresh thread
+ backgroundRefresh(doRefresh);
+ }
+
+ protected void backgroundRefresh(boolean doRefresh) {
+ if(fViewer == null) {
+ fFunctionCache.clear();
+ return;
+ }
+
+ //Parse the document content and extract all function information
+ FunctionDefinition [] allDefs;
+ String content = fDocument.get();
+ if(content != null) {
+ allDefs = parseFunctions(content);
+ } else {
+ allDefs = new FunctionDefinition[0];
+ }
+
+ //Get a copy of the original keys to use as markers
+ Set oldKeys = new HashSet(fFunctionCache.keySet());
+
+ final ArrayList updateList = new ArrayList();
+
+ //Correlate and update as required
+ boolean functionAdded = false;
+ for(int i = 0; i < allDefs.length; i++) {
+ FunctionDefinition newDef = (FunctionDefinition)allDefs[i];
+ final FunctionDefinition oldDef = (FunctionDefinition)fFunctionCache.get(newDef.getName());
+ if(oldDef == null) {
+ fFunctionCache.put(newDef.getName(), newDef);
+ functionAdded = true;
+ } else {
+ oldKeys.remove(newDef.getName());
+ if(!oldDef.offsetsMatch(newDef)) {
+ oldDef.setCharacterOffset(newDef.getCharacterOffset());
+ oldDef.setCharacterEndOffset(newDef.getCharacterEndOffset());
+ updateList.add(oldDef);
+ }
+ }
+ }
+
+ //Check and see if any items were deleted, that causes a full refresh
+ boolean functionRemoved = oldKeys.size() != 0;
+ Iterator it = oldKeys.iterator();
+ while(it.hasNext()) {
+ FunctionDefinition oldDef = (FunctionDefinition)fFunctionCache.get(it.next());
+ fFunctionCache.remove(oldDef.getName());
+ }
+
+ if(!doRefresh) {
+ return;
+ }
+
+ final boolean fullRefresh = functionAdded || functionRemoved;
+
+ Display display = fViewer.getControl().getDisplay();
+ display.syncExec(new Runnable() {
+ public void run() {
+ if(fViewer == null || fViewer.getControl().isDisposed()) {
+ return;
+ }
+
+ if(fullRefresh) {
+ fViewer.refresh();
+ } else {
+ String [] offsetProperty = new String[] { OFFSET_PROPERTY };
+
+ FunctionDefinition [] elements;
+ elements = (FunctionDefinition[])updateList.toArray(new FunctionDefinition[updateList.size()]);
+
+ fViewer.update(elements, offsetProperty);
+ }
+ }
+ });
}
+
+ //This is kind of a weak identification, but it is fairly resilient in the face of errors
+ Pattern fLuaFunctionPattern = Pattern.compile("^\\w*function\\s+(\\w+)\\s*\\(.*$", Pattern.MULTILINE);
+ protected FunctionDefinition [] parseFunctions(String fileContents) {
+ ArrayList<FunctionDefinition> functionList = new ArrayList<FunctionDefinition>();
+
+ Matcher matcher = fLuaFunctionPattern.matcher(fileContents);
+ int offset = 0;
+ while(matcher.find(offset)) {
+ int startOffset = matcher.start();
+ offset = matcher.end();
+ String functionName = matcher.group(1);
+ functionList.add(new FunctionDefinition(functionName, startOffset, offset));
+ }
+
+ return (FunctionDefinition [])functionList.toArray(new FunctionDefinition[functionList.size()]);
+ }
}
View
52 org.keplerproject.ldt.ui/src/org/keplerproject/ldt/ui/editors/outline/LuaOutlineLabelProvider.java
@@ -1,39 +1,35 @@
package org.keplerproject.ldt.ui.editors.outline;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
+import org.keplerproject.ldt.ui.LDTUIPlugin;
-public class LuaOutlineLabelProvider implements ILabelProvider {
-
- public void addListener(ILabelProviderListener listener) {
- // TODO Auto-generated method stub
-
- }
-
- public void dispose() {
- // TODO Auto-generated method stub
-
- }
-
- public boolean isLabelProperty(Object element, String property) {
- // TODO Auto-generated method stub
- return false;
- }
-
- public void removeListener(ILabelProviderListener listener) {
- // TODO Auto-generated method stub
-
- }
+public class LuaOutlineLabelProvider extends LabelProvider {
+ public static String FUNCTION_ICON_PATH = "icons/lua_function.gif";
+ Image functionImage = null;
public Image getImage(Object element) {
- // TODO Auto-generated method stub
- return null;
+ if(functionImage == null) {
+ functionImage = LDTUIPlugin.getImageDescriptor(FUNCTION_ICON_PATH).createImage();
+ }
+ return functionImage;
}
public String getText(Object element) {
- // TODO Auto-generated method stub
- return null;
+ return super.getText(element);
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ if(LuaOutlineContentProvider.OFFSET_PROPERTY.equals(property)) {
+ return false;
+ }
+ return super.isLabelProperty(element, property);
+ }
+
+ public void dispose() {
+ if(functionImage != null) {
+ functionImage.dispose();
+ functionImage = null;
+ }
}
-
}
Please sign in to comment.
Something went wrong with that request. Please try again.