diff --git a/csl.api/nbproject/project.xml b/csl.api/nbproject/project.xml --- a/csl.api/nbproject/project.xml +++ b/csl.api/nbproject/project.xml @@ -393,8 +393,6 @@ org.netbeans.modules.csl.api - org.netbeans.modules.csl.core - org.netbeans.modules.csl.editor org.netbeans.modules.csl.spi org.netbeans.modules.csl.spi.support diff --git a/csl.api/src/META-INF/services/org.netbeans.spi.editor.mimelookup.MimeLookupInitializer b/csl.api/src/META-INF/services/org.netbeans.spi.editor.mimelookup.MimeLookupInitializer deleted file mode 100644 --- a/csl.api/src/META-INF/services/org.netbeans.spi.editor.mimelookup.MimeLookupInitializer +++ /dev/null @@ -1,1 +0,0 @@ -org.netbeans.modules.csl.core.MimeLookupInitializerImpl diff --git a/csl.api/src/org/netbeans/modules/csl/api/GsfLanguage.java b/csl.api/src/org/netbeans/modules/csl/api/GsfLanguage.java --- a/csl.api/src/org/netbeans/modules/csl/api/GsfLanguage.java +++ b/csl.api/src/org/netbeans/modules/csl/api/GsfLanguage.java @@ -45,6 +45,7 @@ import org.netbeans.api.annotations.common.CheckForNull; import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.lexer.Language; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; /** @@ -121,6 +122,7 @@ * no source classpath. * * @return The set of source classpath IDs, can be empty or even null. + * @deprecated Use {@link PathRecognizerRegistration} instead. */ Set getSourcePathIds(); @@ -131,6 +133,7 @@ * * @return The set of library classpath IDs, can be empty or even null. * Please see {@link #getSourcePathIds()} for the exact meaning of those values. + * @deprecated Use {@link PathRecognizerRegistration} instead. */ Set getLibraryPathIds(); @@ -145,6 +148,7 @@ * * @return The set of binary library classpath IDs, can be empty or even null. * Please see {@link #getLibraryPathIds()} for the exact meaning of those values. + * @deprecated Use {@link PathRecognizerRegistration} instead. */ Set getBinaryLibraryPathIds(); } diff --git a/csl.api/src/org/netbeans/modules/csl/core/AbstractCamelCasePosition.java b/csl.api/src/org/netbeans/modules/csl/core/AbstractCamelCasePosition.java --- a/csl.api/src/org/netbeans/modules/csl/core/AbstractCamelCasePosition.java +++ b/csl.api/src/org/netbeans/modules/csl/core/AbstractCamelCasePosition.java @@ -117,7 +117,7 @@ if (name == null) return null; String shortDesc; try { - shortDesc = NbBundle.getBundle(GsfEditorKitFactory.class).getString(name); // NOI18N + shortDesc = NbBundle.getBundle(AbstractCamelCasePosition.class).getString(name); // NOI18N }catch (MissingResourceException mre){ shortDesc = name; } diff --git a/csl.api/src/org/netbeans/modules/csl/core/CamelCaseOperations.java b/csl.api/src/org/netbeans/modules/csl/core/CamelCaseOperations.java --- a/csl.api/src/org/netbeans/modules/csl/core/CamelCaseOperations.java +++ b/csl.api/src/org/netbeans/modules/csl/core/CamelCaseOperations.java @@ -67,7 +67,7 @@ return -1; } - KeystrokeHandler bc = GsfEditorKitFactory.getBracketCompletion(doc, offset); + KeystrokeHandler bc = CslEditorKit.getBracketCompletion(doc, offset); if (bc != null) { int nextOffset = bc.getNextWordOffset(doc, offset, false); if (nextOffset != -1) { @@ -94,7 +94,7 @@ final Document doc = textComponent.getDocument(); - KeystrokeHandler bc = GsfEditorKitFactory.getBracketCompletion(doc, offset); + KeystrokeHandler bc = CslEditorKit.getBracketCompletion(doc, offset); if (bc != null) { int nextOffset = bc.getNextWordOffset( doc, offset, true); @@ -124,7 +124,7 @@ } final Document document = textComponent.getDocument(); Runnable r = new Runnable() { - public void run() { + public @Override void run() { try { if (length > 0) { document.remove(offset, length); diff --git a/csl.api/src/org/netbeans/modules/csl/core/CslEditorKit.java b/csl.api/src/org/netbeans/modules/csl/core/CslEditorKit.java new file mode 100644 --- /dev/null +++ b/csl.api/src/org/netbeans/modules/csl/core/CslEditorKit.java @@ -0,0 +1,519 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2010 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.csl.core; + +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; +import javax.swing.Action; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +import javax.swing.text.JTextComponent; +import javax.swing.text.Keymap; +import javax.swing.text.TextAction; +import org.netbeans.api.editor.mimelookup.MimePath; +import org.netbeans.editor.BaseAction; +import org.netbeans.editor.BaseDocument; +import org.netbeans.editor.BaseKit; +import org.netbeans.editor.SyntaxSupport; +import org.netbeans.editor.Utilities; +import org.netbeans.editor.ext.ExtKit; +import org.netbeans.editor.ext.ExtSyntaxSupport; +import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager; +import org.netbeans.modules.csl.api.GsfLanguage; +import org.netbeans.modules.csl.api.KeystrokeHandler; +import org.netbeans.modules.csl.api.OffsetRange; +import org.netbeans.modules.csl.editor.InstantRenameAction; +import org.netbeans.modules.csl.editor.ToggleBlockCommentAction; +import org.netbeans.modules.csl.editor.hyperlink.GoToSupport; +import org.netbeans.modules.csl.editor.semantic.GoToMarkOccurrencesAction; +import org.netbeans.modules.csl.spi.CommentHandler; +import org.netbeans.modules.csl.spi.DefaultLanguageConfig; +import org.netbeans.modules.editor.NbEditorKit; +import org.openide.awt.Mnemonics; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; + +/** + * + * @author vita + */ +public final class CslEditorKit extends NbEditorKit { + + public static EditorKit createEditorKitInstance(FileObject f) { + String mimeType = detectMimeType(f); + return mimeType != null ? new CslEditorKit(mimeType) : null; + } + + public static org.netbeans.api.lexer.Language createLexerLanguageInstance(FileObject f) { + String mimeType = detectMimeType(f); + if (mimeType != null) { + Language l = LanguageRegistry.getInstance().getLanguageByMimeType(mimeType); + if (l != null) { + return l.getGsfLanguage().getLexerLanguage(); + } + } + return null; + } + + // this is public only because of tests + public CslEditorKit(String mimeType) { + this.mimeType = mimeType; + } + + // ----------------------------------------------------------------------- + // NbEditorKit implementation + // ----------------------------------------------------------------------- + + @Override + public String getContentType() { + return mimeType; + } + + @Override + public Document createDefaultDocument() { + return new GsfDocument(mimeType); + } + + @Override + public SyntaxSupport createSyntaxSupport(final BaseDocument doc) { + return new ExtSyntaxSupport(doc) { + @Override + public int[] findMatchingBlock(int offset, boolean simpleSearch) + throws BadLocationException { + // Do parenthesis matching, if applicable + KeystrokeHandler bracketCompletion = getBracketCompletion(doc, offset); + if (bracketCompletion != null) { + OffsetRange range = bracketCompletion.findMatching(getDocument(), offset/*, simpleSearch*/); + if (range == OffsetRange.NONE) { + return null; + } else { + return new int[] { range.getStart(), range.getEnd() }; + } + } + + return null; + } + }; + } + + @Override + protected void initDocument(BaseDocument doc) { + // XXX This appears in JavaKit, not sure why, but doing it just in case. + //do not ask why, fire bug in the IZ: + CodeTemplateManager.get(doc); + } + + @Override + protected Action[] createActions() { + Action[] superActions = super.createActions(); + Language language = LanguageRegistry.getInstance().getLanguageByMimeType(mimeType); + GsfLanguage gsfLanguage = language.getGsfLanguage(); + + ArrayList actions = new ArrayList(30); + + actions.add(new GsfDefaultKeyTypedAction()); + actions.add(new GsfInsertBreakAction()); + actions.add(new GsfDeleteCharAction(deletePrevCharAction, false)); + + String lineCommentPrefix = (gsfLanguage != null) ? gsfLanguage.getLineCommentPrefix() : null; + if (lineCommentPrefix != null) { + actions.add(new CommentAction(lineCommentPrefix)); + actions.add(new UncommentAction(lineCommentPrefix)); + actions.add(new ToggleCommentAction(lineCommentPrefix)); + } + + if(gsfLanguage instanceof DefaultLanguageConfig) { + CommentHandler ch = ((DefaultLanguageConfig)gsfLanguage).getCommentHandler(); + if(ch != null) { + actions.add(new ToggleBlockCommentAction(ch)); + } + + } + + actions.add(new InstantRenameAction()); + actions.add(new GenericGoToDeclarationAction()); + actions.add(new GenericGenerateGoToPopupAction()); + actions.add(new SelectCodeElementAction(SelectCodeElementAction.selectNextElementAction, true)); + actions.add(new SelectCodeElementAction(SelectCodeElementAction.selectPreviousElementAction, false)); + //actions.add(new ExpandAllCodeBlockFolds()); + //actions.add(new CollapseAllCodeBlockFolds()); + actions.add(new NextCamelCasePosition(findAction(superActions, nextWordAction))); + actions.add(new PreviousCamelCasePosition(findAction(superActions, previousWordAction))); + actions.add(new SelectNextCamelCasePosition(findAction(superActions, selectionNextWordAction))); + actions.add(new SelectPreviousCamelCasePosition(findAction(superActions, selectionPreviousWordAction))); + actions.add(new DeleteToNextCamelCasePosition(findAction(superActions, removeNextWordAction))); + actions.add(new DeleteToPreviousCamelCasePosition(findAction(superActions, removePreviousWordAction))); + + if (language.hasOccurrencesFinder()) { + actions.add(new GoToMarkOccurrencesAction(false)); + actions.add(new GoToMarkOccurrencesAction(true)); + } + + return TextAction.augmentList(superActions, + actions.toArray(new Action[actions.size()])); + } + + // ----------------------------------------------------------------------- + // Private implementation + // ----------------------------------------------------------------------- + + private final String mimeType; + + private static String detectMimeType(FileObject f) { + String mimeType = f.getParent().getPath().substring("Editors/".length()); //NOI18N + return MimePath.validate(mimeType) && mimeType.length() > 0 ? mimeType : null; + } + + private static Action findAction(Action [] actions, String name) { + for(Action a : actions) { + Object nameObj = a.getValue(Action.NAME); + if (nameObj instanceof String && name.equals(nameObj)) { + return a; + } + } + return null; + } + + /* package */ static KeystrokeHandler getBracketCompletion(Document doc, int offset) { + BaseDocument baseDoc = (BaseDocument)doc; + List list = LanguageRegistry.getInstance().getEmbeddedLanguages(baseDoc, offset); + for (Language l : list) { + if (l.getBracketCompletion() != null) { + return l.getBracketCompletion(); + } + } + + return null; + } + + /** + * Returns true if bracket completion is enabled in options. + */ + private static boolean completionSettingEnabled() { + //return ((Boolean)Settings.getValue(GsfEditorKit.class, JavaSettingsNames.PAIR_CHARACTERS_COMPLETION)).booleanValue(); + return true; + } + + private final class GsfDefaultKeyTypedAction extends ExtDefaultKeyTypedAction { + private JTextComponent currentTarget; + + @Override + public void actionPerformed(ActionEvent evt, JTextComponent target) { + currentTarget = target; + super.actionPerformed(evt, target); + currentTarget = null; + } + + @Override + protected void insertString(BaseDocument doc, int dotPos, Caret caret, String str, + boolean overwrite) throws BadLocationException { + if (completionSettingEnabled()) { + KeystrokeHandler bracketCompletion = getBracketCompletion(doc, dotPos); + + if (bracketCompletion != null) { + // TODO - check if we're in a comment etc. and if so, do nothing + boolean handled = + bracketCompletion.beforeCharInserted(doc, dotPos, currentTarget, + str.charAt(0)); + + if (!handled) { + super.insertString(doc, dotPos, caret, str, overwrite); + handled = bracketCompletion.afterCharInserted(doc, dotPos, currentTarget, + str.charAt(0)); + } + + return; + } + } + + super.insertString(doc, dotPos, caret, str, overwrite); + } + + @Override + protected void replaceSelection(JTextComponent target, int dotPos, Caret caret, + String str, boolean overwrite) throws BadLocationException { + char insertedChar = str.charAt(0); + Document document = target.getDocument(); + + if (document instanceof BaseDocument) { + BaseDocument doc = (BaseDocument)document; + + if (completionSettingEnabled()) { + KeystrokeHandler bracketCompletion = getBracketCompletion(doc, dotPos); + + if (bracketCompletion != null) { + try { + int caretPosition = caret.getDot(); + + boolean handled = + bracketCompletion.beforeCharInserted(doc, caretPosition, + target, insertedChar); + + int p0 = Math.min(caret.getDot(), caret.getMark()); + int p1 = Math.max(caret.getDot(), caret.getMark()); + + if (p0 != p1) { + doc.remove(p0, p1 - p0); + } + + if (!handled) { + if ((str != null) && (str.length() > 0)) { + doc.insertString(p0, str, null); + } + + bracketCompletion.afterCharInserted(doc, caret.getDot() - 1, + target, insertedChar); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + + return; + } + } + } + + super.replaceSelection(target, dotPos, caret, str, overwrite); + } + } + + private final class GsfInsertBreakAction extends InsertBreakAction { + static final long serialVersionUID = -1506173310438326380L; + + @Override + protected Object beforeBreak(JTextComponent target, BaseDocument doc, Caret caret) { + if (completionSettingEnabled()) { + KeystrokeHandler bracketCompletion = getBracketCompletion(doc, caret.getDot()); + + if (bracketCompletion != null) { + try { + int newOffset = bracketCompletion.beforeBreak(doc, caret.getDot(), target); + + if (newOffset >= 0) { + return new Integer(newOffset); + } + } catch (BadLocationException ble) { + Exceptions.printStackTrace(ble); + } + } + } + + // return Boolean.TRUE; + return null; + } + + @Override + protected void afterBreak(JTextComponent target, BaseDocument doc, Caret caret, + Object cookie) { + if (completionSettingEnabled()) { + if (cookie != null) { + if (cookie instanceof Integer) { + // integer + int dotPos = ((Integer)cookie).intValue(); + if (dotPos != -1) { + caret.setDot(dotPos); + } else { + int nowDotPos = caret.getDot(); + caret.setDot(nowDotPos + 1); + } + } + } + } + } + } + + private final class GsfDeleteCharAction extends ExtDeleteCharAction { + private JTextComponent currentTarget; + + public GsfDeleteCharAction(String nm, boolean nextChar) { + super(nm, nextChar); + } + + @Override + public void actionPerformed(ActionEvent evt, JTextComponent target) { + currentTarget = target; + super.actionPerformed(evt, target); + currentTarget = null; + } + + @Override + protected void charBackspaced(BaseDocument doc, int dotPos, Caret caret, char ch) + throws BadLocationException { + if (completionSettingEnabled()) { + KeystrokeHandler bracketCompletion = getBracketCompletion(doc, dotPos); + + if (bracketCompletion != null) { + boolean success = bracketCompletion.charBackspaced(doc, dotPos, currentTarget, ch); + return; + } + } + super.charBackspaced(doc, dotPos, caret, ch); + } + } + + private final class GenericGoToDeclarationAction extends GotoDeclarationAction { + @Override + public boolean gotoDeclaration(JTextComponent target) { + GoToSupport.performGoTo((BaseDocument)target.getDocument(), + target.getCaretPosition()); + + return true; + } + } + + private final class GenericGenerateGoToPopupAction extends NbGenerateGoToPopupAction { + @Override + public void actionPerformed(ActionEvent evt, JTextComponent target) { + } + + private void addAcceleretors(Action a, JMenuItem item, JTextComponent target) { + // Try to get the accelerator + Keymap km = target.getKeymap(); + + if (km != null) { + KeyStroke[] keys = km.getKeyStrokesForAction(a); + + if ((keys != null) && (keys.length > 0)) { + item.setAccelerator(keys[0]); + } else if (a != null) { + KeyStroke ks = (KeyStroke)a.getValue(Action.ACCELERATOR_KEY); + + if (ks != null) { + item.setAccelerator(ks); + } + } + } + } + + private void addAction(JTextComponent target, JMenu menu, Action a) { + if (a != null) { + String actionName = (String)a.getValue(Action.NAME); + JMenuItem item = null; + + if (a instanceof BaseAction) { + item = ((BaseAction)a).getPopupMenuItem(target); + } + + if (item == null) { + // gets trimmed text that doesn' contain "go to" + String itemText = (String)a.getValue(ExtKit.TRIMMED_TEXT); + + if (itemText == null) { + itemText = getItemText(target, actionName, a); + } + + if (itemText != null) { + item = new JMenuItem(itemText); + Mnemonics.setLocalizedText(item, itemText); + item.addActionListener(a); + addAcceleretors(a, item, target); + item.setEnabled(a.isEnabled()); + + Object helpID = a.getValue("helpID"); // NOI18N + + if ((helpID != null) && (helpID instanceof String)) { + item.putClientProperty("HelpID", helpID); // NOI18N + } + } else { + if (ExtKit.gotoSourceAction.equals(actionName)) { + item = new JMenuItem(NbBundle.getBundle(CslEditorKit.class) + .getString("goto_source_open_source_not_formatted")); //NOI18N + addAcceleretors(a, item, target); + item.setEnabled(false); + } + } + } + + if (item != null) { + menu.add(item); + } + } + } + + private void addAction(JTextComponent target, JMenu menu, String actionName) { + BaseKit kit = Utilities.getKit(target); + + if (kit == null) { + return; + } + + Action a = kit.getActionByName(actionName); + + if (a != null) { + addAction(target, menu, a); + } else { // action-name is null, add the separator + menu.addSeparator(); + } + } + + private String getItemText(JTextComponent target, String actionName, Action a) { + String itemText; + + if (a instanceof BaseAction) { + itemText = ((BaseAction)a).getPopupMenuText(target); + } else { + itemText = actionName; + } + + return itemText; + } + + @Override + public JMenuItem getPopupMenuItem(final JTextComponent target) { + String menuText = + NbBundle.getBundle(CslEditorKit.class).getString("generate-goto-popup"); //NOI18N + JMenu jm = new JMenu(menuText); + //addAction(target, jm, ExtKit.gotoSourceAction); + addAction(target, jm, ExtKit.gotoDeclarationAction); + //addAction(target, jm, gotoSuperImplementationAction); + //addAction(target, jm, ExtKit.gotoAction); + return jm; + } + } + + +} diff --git a/csl.api/src/org/netbeans/modules/csl/core/GsfDocument.java b/csl.api/src/org/netbeans/modules/csl/core/GsfDocument.java --- a/csl.api/src/org/netbeans/modules/csl/core/GsfDocument.java +++ b/csl.api/src/org/netbeans/modules/csl/core/GsfDocument.java @@ -50,24 +50,22 @@ * @author Tor Norbye */ public class GsfDocument extends NbEditorDocument { - private Language language; + + private GsfLanguage language = null; - public GsfDocument(Language language) { - super(language.getMimeType()); - if (language.getGsfLanguage() != null) { - putProperty(org.netbeans.api.lexer.Language.class, language.getGsfLanguage().getLexerLanguage()); - } - - this.language = language; + public GsfDocument(String mimeType) { + super(mimeType); } @Override public boolean isIdentifierPart(char ch) { - GsfLanguage gsfLanguage = language.getGsfLanguage(); - if (gsfLanguage != null) { - return gsfLanguage.isIdentifierChar(ch); + if (language == null) { + Language l = LanguageRegistry.getInstance().getLanguageByMimeType((String) getProperty("mimeType")); //NOI18N + if (l != null) { + language = l.getGsfLanguage(); + } } - - return super.isIdentifierPart(ch); + + return language != null ? language.isIdentifierChar(ch) : super.isIdentifierPart(ch); } } diff --git a/csl.api/src/org/netbeans/modules/csl/core/GsfEditorKitFactory.java b/csl.api/src/org/netbeans/modules/csl/core/GsfEditorKitFactory.java deleted file mode 100644 --- a/csl.api/src/org/netbeans/modules/csl/core/GsfEditorKitFactory.java +++ /dev/null @@ -1,561 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.netbeans.modules.csl.core; - -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.List; -import javax.swing.Action; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.KeyStroke; -import javax.swing.text.BadLocationException; -import javax.swing.text.Caret; -import javax.swing.text.Document; -import javax.swing.text.JTextComponent; -import javax.swing.text.Keymap; -import javax.swing.text.TextAction; -import org.netbeans.api.editor.fold.FoldHierarchy; -import org.netbeans.api.editor.fold.FoldUtilities; -import org.netbeans.modules.csl.api.KeystrokeHandler; -import org.netbeans.modules.csl.api.GsfLanguage; -import org.netbeans.modules.csl.api.OffsetRange; -import org.netbeans.editor.BaseAction; -import org.netbeans.editor.BaseDocument; -import org.netbeans.editor.BaseKit; -import org.netbeans.editor.BaseKit.InsertBreakAction; -import org.netbeans.editor.SyntaxSupport; -import org.netbeans.editor.Utilities; -import org.netbeans.editor.ext.ExtKit; -import org.netbeans.editor.ext.ExtKit.ToggleCommentAction; -import org.netbeans.editor.ext.ExtSyntaxSupport; -import org.netbeans.lib.editor.codetemplates.api.CodeTemplateManager; -import org.netbeans.modules.csl.spi.CommentHandler; -import org.netbeans.modules.editor.NbEditorKit; -import org.netbeans.modules.csl.editor.InstantRenameAction; -import org.netbeans.modules.csl.editor.ToggleBlockCommentAction; -import org.netbeans.modules.csl.editor.fold.GsfFoldManager; -import org.netbeans.modules.csl.editor.hyperlink.GoToSupport; -import org.netbeans.modules.csl.editor.semantic.GoToMarkOccurrencesAction; -import org.netbeans.modules.csl.spi.DefaultLanguageConfig; -import org.openide.awt.Mnemonics; -import org.openide.util.Exceptions; -import org.openide.util.NbBundle; - - -/** - * This class represents a generic Editor Kit which is shared by a number of different - * languages. The EditorKit is an innerclass, because its superclass (BaseKit) calls - * getContentType() as part of its constructor. Our getContentType implementation - * relies on accessing one of the fields passed in to our constructor; but when the - * super constructor is calling getContentType(), our own constructor has not yet been - * called. This is worked around by having an outer class which holds the field - * we need at constructor time (langauge). - * - * @author Tor Norbye - * @author Jan Jancura - */ -public class GsfEditorKitFactory { - public static final String expandAllCodeBlockFolds = "expand-all-code-block-folds"; //NOI18N - public static final String collapseAllCodeBlockFolds = "collapse-all-code-block-folds"; //NOI18N - - Language language; - String mimeType; - - public GsfEditorKitFactory(Language language) { - assert language != null; - this.language = language; - this.mimeType = language.getMimeType(); - } - - /** - * Return the actual kit. This is necessary because NbEditorKit's constructor - * winds up calling getContentType(), before we've actually had a chance to - * construct our own editor kit (where getContentType() depends on construction - * of the object. The trick is to use an outer class, construct that first, and - * - */ - public GsfEditorKit kit() { - return new GsfEditorKit(); - } - - public static Action findAction(Action [] actions, String name) { - for(Action a : actions) { - Object nameObj = a.getValue(Action.NAME); - if (nameObj instanceof String && name.equals(nameObj)) { - return a; - } - } - return null; - } - - static KeystrokeHandler getBracketCompletion(Document doc, int offset) { - BaseDocument baseDoc = (BaseDocument)doc; - List list = LanguageRegistry.getInstance().getEmbeddedLanguages(baseDoc, offset); - for (Language l : list) { - if (l.getBracketCompletion() != null) { - return l.getBracketCompletion(); - } - } - - return null; - } - - /** - * Returns true if bracket completion is enabled in options. - */ - private static boolean completionSettingEnabled() { - //return ((Boolean)Settings.getValue(GsfEditorKit.class, JavaSettingsNames.PAIR_CHARACTERS_COMPLETION)).booleanValue(); - return true; - } - - public class GsfEditorKit extends NbEditorKit { - - public GsfEditorKit() { - } - - @Override - public String getContentType() { - return language.getMimeType(); - } - - @Override - public Document createDefaultDocument() { - Document doc = new GsfDocument(language); - doc.putProperty("mimeType", getContentType()); //NOI18N - return doc; - } - - @Override - public SyntaxSupport createSyntaxSupport(final BaseDocument doc) { - return new ExtSyntaxSupport(doc) { - @Override - public int[] findMatchingBlock(int offset, boolean simpleSearch) - throws BadLocationException { - // Do parenthesis matching, if applicable - KeystrokeHandler bracketCompletion = getBracketCompletion(doc, offset); - if (bracketCompletion != null) { - OffsetRange range = bracketCompletion.findMatching(getDocument(), offset/*, simpleSearch*/); - if (range == OffsetRange.NONE) { - return null; - } else { - return new int[] { range.getStart(), range.getEnd() }; - } - } - - return null; - } - }; - } - - @Override - protected void initDocument(BaseDocument doc) { - // XXX This appears in JavaKit, not sure why, but doing it just in case. - //do not ask why, fire bug in the IZ: - CodeTemplateManager.get(doc); - } - - @Override - public Object clone() { - return new GsfEditorKit(); - } - - @Override - protected Action[] createActions() { - Action[] superActions = super.createActions(); - GsfLanguage gsfLanguage = language.getGsfLanguage(); - - ArrayList actions = new ArrayList(30); - - actions.add(new GsfDefaultKeyTypedAction()); - actions.add(new GsfInsertBreakAction()); - actions.add(new GsfDeleteCharAction(deletePrevCharAction, false)); - - String lineCommentPrefix = (gsfLanguage != null) ? gsfLanguage.getLineCommentPrefix() : null; - if (lineCommentPrefix != null) { - actions.add(new CommentAction(lineCommentPrefix)); - actions.add(new UncommentAction(lineCommentPrefix)); - actions.add(new ToggleCommentAction(lineCommentPrefix)); - } - - if(gsfLanguage instanceof DefaultLanguageConfig) { - CommentHandler ch = ((DefaultLanguageConfig)gsfLanguage).getCommentHandler(); - if(ch != null) { - actions.add(new ToggleBlockCommentAction(ch)); - } - - } - - actions.add(new InstantRenameAction()); - actions.add(new GenericGoToDeclarationAction()); - actions.add(new GenericGenerateGoToPopupAction()); - actions.add(new SelectCodeElementAction(SelectCodeElementAction.selectNextElementAction, true)); - actions.add(new SelectCodeElementAction(SelectCodeElementAction.selectPreviousElementAction, false)); - //actions.add(new ExpandAllCodeBlockFolds()); - //actions.add(new CollapseAllCodeBlockFolds()); - actions.add(new NextCamelCasePosition(findAction(superActions, nextWordAction))); - actions.add(new PreviousCamelCasePosition(findAction(superActions, previousWordAction))); - actions.add(new SelectNextCamelCasePosition(findAction(superActions, selectionNextWordAction))); - actions.add(new SelectPreviousCamelCasePosition(findAction(superActions, selectionPreviousWordAction))); - actions.add(new DeleteToNextCamelCasePosition(findAction(superActions, removeNextWordAction))); - actions.add(new DeleteToPreviousCamelCasePosition(findAction(superActions, removePreviousWordAction))); - - if (language.hasOccurrencesFinder()) { - actions.add(new GoToMarkOccurrencesAction(false)); - actions.add(new GoToMarkOccurrencesAction(true)); - } - - return TextAction.augmentList(superActions, - actions.toArray(new Action[actions.size()])); - } - - public class GsfDefaultKeyTypedAction extends ExtDefaultKeyTypedAction { - private JTextComponent currentTarget; - - @Override - public void actionPerformed(ActionEvent evt, JTextComponent target) { - currentTarget = target; - super.actionPerformed(evt, target); - currentTarget = null; - } - - @Override - protected void insertString(BaseDocument doc, int dotPos, Caret caret, String str, - boolean overwrite) throws BadLocationException { - if (completionSettingEnabled()) { - KeystrokeHandler bracketCompletion = getBracketCompletion(doc, dotPos); - - if (bracketCompletion != null) { - // TODO - check if we're in a comment etc. and if so, do nothing - boolean handled = - bracketCompletion.beforeCharInserted(doc, dotPos, currentTarget, - str.charAt(0)); - - if (!handled) { - super.insertString(doc, dotPos, caret, str, overwrite); - handled = bracketCompletion.afterCharInserted(doc, dotPos, currentTarget, - str.charAt(0)); - } - - return; - } - } - - super.insertString(doc, dotPos, caret, str, overwrite); - } - - @Override - protected void replaceSelection(JTextComponent target, int dotPos, Caret caret, - String str, boolean overwrite) throws BadLocationException { - char insertedChar = str.charAt(0); - Document document = target.getDocument(); - - if (document instanceof BaseDocument) { - BaseDocument doc = (BaseDocument)document; - - if (completionSettingEnabled()) { - KeystrokeHandler bracketCompletion = getBracketCompletion(doc, dotPos); - - if (bracketCompletion != null) { - try { - int caretPosition = caret.getDot(); - - boolean handled = - bracketCompletion.beforeCharInserted(doc, caretPosition, - target, insertedChar); - - int p0 = Math.min(caret.getDot(), caret.getMark()); - int p1 = Math.max(caret.getDot(), caret.getMark()); - - if (p0 != p1) { - doc.remove(p0, p1 - p0); - } - - if (!handled) { - if ((str != null) && (str.length() > 0)) { - doc.insertString(p0, str, null); - } - - bracketCompletion.afterCharInserted(doc, caret.getDot() - 1, - target, insertedChar); - } - } catch (BadLocationException e) { - e.printStackTrace(); - } - - return; - } - } - } - - super.replaceSelection(target, dotPos, caret, str, overwrite); - } - } - - public class GsfInsertBreakAction extends InsertBreakAction { - static final long serialVersionUID = -1506173310438326380L; - - @Override - protected Object beforeBreak(JTextComponent target, BaseDocument doc, Caret caret) { - if (completionSettingEnabled()) { - KeystrokeHandler bracketCompletion = getBracketCompletion(doc, caret.getDot()); - - if (bracketCompletion != null) { - try { - int newOffset = bracketCompletion.beforeBreak(doc, caret.getDot(), target); - - if (newOffset >= 0) { - return new Integer(newOffset); - } - } catch (BadLocationException ble) { - Exceptions.printStackTrace(ble); - } - } - } - - // return Boolean.TRUE; - return null; - } - - @Override - protected void afterBreak(JTextComponent target, BaseDocument doc, Caret caret, - Object cookie) { - if (completionSettingEnabled()) { - if (cookie != null) { - if (cookie instanceof Integer) { - // integer - int dotPos = ((Integer)cookie).intValue(); - if (dotPos != -1) { - caret.setDot(dotPos); - } else { - int nowDotPos = caret.getDot(); - caret.setDot(nowDotPos + 1); - } - } - } - } - } - } - - public class GsfDeleteCharAction extends ExtDeleteCharAction { - private JTextComponent currentTarget; - - public GsfDeleteCharAction(String nm, boolean nextChar) { - super(nm, nextChar); - } - - @Override - public void actionPerformed(ActionEvent evt, JTextComponent target) { - currentTarget = target; - super.actionPerformed(evt, target); - currentTarget = null; - } - - @Override - protected void charBackspaced(BaseDocument doc, int dotPos, Caret caret, char ch) - throws BadLocationException { - if (completionSettingEnabled()) { - KeystrokeHandler bracketCompletion = getBracketCompletion(doc, dotPos); - - if (bracketCompletion != null) { - boolean success = bracketCompletion.charBackspaced(doc, dotPos, currentTarget, ch); - return; - } - } - super.charBackspaced(doc, dotPos, caret, ch); - } - } - - private class GenericGoToDeclarationAction extends GotoDeclarationAction { - @Override - public boolean gotoDeclaration(JTextComponent target) { - GoToSupport.performGoTo((BaseDocument)target.getDocument(), - target.getCaretPosition()); - - return true; - } - } - - private class GenericGenerateGoToPopupAction extends NbGenerateGoToPopupAction { - @Override - public void actionPerformed(ActionEvent evt, JTextComponent target) { - } - - private void addAcceleretors(Action a, JMenuItem item, JTextComponent target) { - // Try to get the accelerator - Keymap km = target.getKeymap(); - - if (km != null) { - KeyStroke[] keys = km.getKeyStrokesForAction(a); - - if ((keys != null) && (keys.length > 0)) { - item.setAccelerator(keys[0]); - } else if (a != null) { - KeyStroke ks = (KeyStroke)a.getValue(Action.ACCELERATOR_KEY); - - if (ks != null) { - item.setAccelerator(ks); - } - } - } - } - - private void addAction(JTextComponent target, JMenu menu, Action a) { - if (a != null) { - String actionName = (String)a.getValue(Action.NAME); - JMenuItem item = null; - - if (a instanceof BaseAction) { - item = ((BaseAction)a).getPopupMenuItem(target); - } - - if (item == null) { - // gets trimmed text that doesn' contain "go to" - String itemText = (String)a.getValue(ExtKit.TRIMMED_TEXT); - - if (itemText == null) { - itemText = getItemText(target, actionName, a); - } - - if (itemText != null) { - item = new JMenuItem(itemText); - Mnemonics.setLocalizedText(item, itemText); - item.addActionListener(a); - addAcceleretors(a, item, target); - item.setEnabled(a.isEnabled()); - - Object helpID = a.getValue("helpID"); // NOI18N - - if ((helpID != null) && (helpID instanceof String)) { - item.putClientProperty("HelpID", helpID); // NOI18N - } - } else { - if (ExtKit.gotoSourceAction.equals(actionName)) { - item = new JMenuItem(NbBundle.getBundle(GsfEditorKit.class) - .getString("goto_source_open_source_not_formatted")); //NOI18N - addAcceleretors(a, item, target); - item.setEnabled(false); - } - } - } - - if (item != null) { - menu.add(item); - } - } - } - - private void addAction(JTextComponent target, JMenu menu, String actionName) { - BaseKit kit = Utilities.getKit(target); - - if (kit == null) { - return; - } - - Action a = kit.getActionByName(actionName); - - if (a != null) { - addAction(target, menu, a); - } else { // action-name is null, add the separator - menu.addSeparator(); - } - } - - private String getItemText(JTextComponent target, String actionName, Action a) { - String itemText; - - if (a instanceof BaseAction) { - itemText = ((BaseAction)a).getPopupMenuText(target); - } else { - itemText = actionName; - } - - return itemText; - } - - @Override - public JMenuItem getPopupMenuItem(final JTextComponent target) { - String menuText = - NbBundle.getBundle(GsfEditorKit.class).getString("generate-goto-popup"); //NOI18N - JMenu jm = new JMenu(menuText); - //addAction(target, jm, ExtKit.gotoSourceAction); - addAction(target, jm, ExtKit.gotoDeclarationAction); - //addAction(target, jm, gotoSuperImplementationAction); - //addAction(target, jm, ExtKit.gotoAction); - return jm; - } - } - } - - public static class ExpandAllCodeBlockFolds extends BaseAction{ - public ExpandAllCodeBlockFolds(){ - super(expandAllCodeBlockFolds); - putValue(SHORT_DESCRIPTION, NbBundle.getBundle(GsfEditorKitFactory.class).getString("expand-all-code-block-folds")); - putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(GsfEditorKitFactory.class).getString("popup-expand-all-code-block-folds")); - } - - public void actionPerformed(ActionEvent evt, JTextComponent target) { - FoldHierarchy hierarchy = FoldHierarchy.get(target); - // Hierarchy locking done in the utility method - List types = new ArrayList(); - types.add(GsfFoldManager.CODE_BLOCK_FOLD_TYPE); - //types.add(GsfFoldManager.IMPORTS_FOLD_TYPE); - FoldUtilities.expand(hierarchy, types); - } - } - - public static class CollapseAllCodeBlockFolds extends BaseAction{ - public CollapseAllCodeBlockFolds(){ - super(collapseAllCodeBlockFolds); - putValue(SHORT_DESCRIPTION, NbBundle.getBundle(GsfEditorKitFactory.class).getString("collapse-all-code-block-folds")); - putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(GsfEditorKitFactory.class).getString("popup-collapse-all-code-block-folds")); - } - - public void actionPerformed(ActionEvent evt, JTextComponent target) { - FoldHierarchy hierarchy = FoldHierarchy.get(target); - // Hierarchy locking done in the utility method - List types = new ArrayList(); - types.add(GsfFoldManager.CODE_BLOCK_FOLD_TYPE); - ///types.add(GsfFoldManager.IMPORTS_FOLD_TYPE); - FoldUtilities.collapse(hierarchy, types); - } - } -} diff --git a/csl.api/src/org/netbeans/modules/csl/core/LanguageRegistrationProcessor.java b/csl.api/src/org/netbeans/modules/csl/core/LanguageRegistrationProcessor.java --- a/csl.api/src/org/netbeans/modules/csl/core/LanguageRegistrationProcessor.java +++ b/csl.api/src/org/netbeans/modules/csl/core/LanguageRegistrationProcessor.java @@ -48,12 +48,15 @@ import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.util.ElementFilter; import javax.swing.JSeparator; +import javax.swing.text.EditorKit; import org.netbeans.api.editor.mimelookup.MimePath; +import org.netbeans.api.lexer.Language; import org.netbeans.lib.editor.codetemplates.CodeTemplateCompletionProvider; import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProviderExt; import org.netbeans.modules.csl.editor.GsfCodeFoldingSideBarFactory; @@ -68,6 +71,8 @@ import org.netbeans.modules.csl.navigation.ClassMemberPanel; import org.netbeans.modules.csl.spi.LanguageRegistration; import org.netbeans.modules.editor.errorstripe.privatespi.MarkProviderCreator; +import org.netbeans.modules.editor.indent.spi.IndentTask; +import org.netbeans.modules.editor.indent.spi.ReformatTask; import org.netbeans.modules.parsing.spi.ParserFactory; import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory; import org.netbeans.modules.parsing.spi.indexing.PathRecognizer; @@ -107,6 +112,15 @@ throw new LayerGenerationException("Class " + cls + " is not subclass of " + dlc, e); //NOI18N } + boolean isAnnotatedByPathRecognizerRegistration = false; + TypeElement prr = processingEnv.getElementUtils().getTypeElement("org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration"); //NOI18N + for(AnnotationMirror am : cls.getAnnotationMirrors()) { + if (am.getAnnotationType().asElement().equals(prr)) { + isAnnotatedByPathRecognizerRegistration = true; + break; + } + } + List methodsList = ElementFilter.methodsIn(cls.getEnclosedElements()); Map methods = new HashMap(methodsList.size()); for(ExecutableElement m : methodsList) { @@ -126,10 +140,20 @@ } if (!languageRegistration.useCustomEditorKit()) { + registerEditorKit(lb, mimeType); registerLoader(lb, mimeType); - registerPathRecognizer(lb, mimeType); - registerParser(lb, mimeType); - registerIndexer(lb, mimeType); + if (methods.containsKey("getLexerLanguage")) { //NOI18N + registerLexer(lb, mimeType); + } + if (methods.containsKey("getParser")) { //NOI18N + registerParser(lb, mimeType); + } + if (methods.containsKey("getIndexerFactory")) { //NOI18N + registerIndexer(lb, mimeType); + if (!isAnnotatedByPathRecognizerRegistration) { + registerPathRecognizer(lb, mimeType); + } + } registerCodeCompletion(lb, mimeType); registerCodeFolding(lb, mimeType); registerCodeTemplates(lb, mimeType); @@ -140,6 +164,9 @@ registerUpToDateStatus(lb, mimeType); registerContextMenu(lb, mimeType, methods); registerCommentUncommentToolbarButtons(lb, mimeType); + if (methods.containsKey("getFormatter")) { //NOI18N + registerFormatterIndenter(lb, mimeType); + } } } } @@ -431,6 +458,19 @@ // } } + private static void registerEditorKit(LayerBuilder b, String mimeType) { + instanceFile(b, "Editors/" + mimeType, null, CslEditorKit.class, "createEditorKitInstance", EditorKit.class).write(); //NOI18N + } + + private static void registerLexer(LayerBuilder b, String mimeType) { + instanceFile(b, "Editors/" + mimeType, null, CslEditorKit.class, "createLexerLanguageInstance", Language.class).write(); //NOI18N + } + + private static void registerFormatterIndenter(LayerBuilder b, String mimeType) { + instanceFile(b, "Editors/" + mimeType, null, GsfReformatTaskFactory.class, null, ReformatTask.class).write(); //NOI18N + instanceFile(b, "Editors/" + mimeType, null, GsfIndentTaskFactory.class, null, IndentTask.class).write(); //NOI18N + } + private static String makeFilesystemName(String s) { StringBuilder sb = new StringBuilder(s.length()); for(int i = 0; i < s.length(); i++) { diff --git a/csl.api/src/org/netbeans/modules/csl/core/MimeLookupInitializerImpl.java b/csl.api/src/org/netbeans/modules/csl/core/MimeLookupInitializerImpl.java deleted file mode 100644 --- a/csl.api/src/org/netbeans/modules/csl/core/MimeLookupInitializerImpl.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package org.netbeans.modules.csl.core; - -import java.util.HashMap; -import java.util.Map; -import org.netbeans.modules.csl.core.GsfIndentTaskFactory; -import org.netbeans.spi.editor.mimelookup.MimeLookupInitializer; -import org.openide.util.Lookup; -import org.openide.util.lookup.InstanceContent; -import org.openide.util.lookup.Lookups; - - -/** - * Listen for editor lookup requests for a particular mime type, and lazily - * initialize language support and construct an editor kit for the given - * mime type. - * - * Based on MimeLookupInitializer in the Schliemann prototype by Jan Jancura. - * - * @author Jan Jancura - * @author Tor Norbye - */ -public class MimeLookupInitializerImpl implements MimeLookupInitializer { - - private static final int EDITOR_KIT_ID = 1; - private static final int INDENT_ID = 2; - private static final int FORMAT_ID = 3; - private static final int BRACES_ID = 4; - - private String[] mimeTypes; - private Map children = new HashMap(); // - private Lookup lookup; - - public MimeLookupInitializerImpl() { - this(new String[0]); - } - - public MimeLookupInitializerImpl(String[] mimeTypes) { - this.mimeTypes = mimeTypes; - } - - /** - * Retrieves a Lookup.Result of MimeLookupInitializers for the given sub-mimeType. - * - * @param mimeType mime-type string representation e.g. "text/x-java" - * @return non-null lookup result of MimeLookupInitializer(s). - *
- * Typically there should be just one child initializer although if there - * will be more than one all of them will be taken into consideration. - *
- * If there will be no specific initializers for the particular mime-type - * then an empty result should be returned. - */ - public Lookup.Result child(String mimeType) { - synchronized (children) { - String[] newMimeType = new String[mimeTypes.length + 1]; - System.arraycopy(mimeTypes, 0, newMimeType, 0, mimeTypes.length); - newMimeType[mimeTypes.length] = mimeType; - - Lookup.Result child = children.get(mimeType); - - if (child == null) { - child = Lookups.fixed(new Object[]{new MimeLookupInitializerImpl(newMimeType)}).lookup(new Lookup.Template(MimeLookupInitializerImpl.class)); - children.put(mimeType, child); - } - - return child; - } - } - - /** - * Lookup providing mime-type sensitive or global-level data - * depending on which level this initializer is defined. - * - * @return Lookup or null, if there are no lookup-able objects for mime or global level. - */ - public Lookup lookup() { - if (lookup == null) { - if (mimeTypes.length != 1) { - lookup = Lookup.EMPTY; - - return lookup; - } - - if (LanguageRegistry.getInstance().isSupported(mimeTypes[0])) { - final Language language = LanguageRegistry.getInstance().getLanguageByMimeType(mimeTypes[0]); - assert language != null; - - if (language.useCustomEditorKit()) { - return null; - } - - Integer[] supportedOps = null; - if (language.hasFormatter()) { - supportedOps = new Integer[]{Integer.valueOf(EDITOR_KIT_ID), Integer.valueOf(INDENT_ID), Integer.valueOf(FORMAT_ID) }; - } else { - supportedOps = new Integer[]{Integer.valueOf(EDITOR_KIT_ID), Integer.valueOf(INDENT_ID) }; - } - - lookup = Lookups.fixed(supportedOps, new InstanceContent.Convertor() { - - public Object convert(Integer i) { - switch (i.intValue()) { - case EDITOR_KIT_ID: { - GsfEditorKitFactory outer = new GsfEditorKitFactory(language); - - return outer.kit(); - } - //case BRACES_ID: { - // return new BraceHighlighting(mimeTypes[0]); - //} - case FORMAT_ID: - return new GsfReformatTaskFactory(); - case INDENT_ID: - return new GsfIndentTaskFactory(); - } - - return null; - } - - public Class type(Integer i) { - switch (i.intValue()) { - case EDITOR_KIT_ID: - return GsfEditorKitFactory.GsfEditorKit.class; - case FORMAT_ID: - return GsfReformatTaskFactory.class; - case INDENT_ID: - return GsfIndentTaskFactory.class; - //case BRACES_ID: - // return BracesMatcherFactory.class; - } - - - return null; - } - - public String id(Integer i) { - return i.toString(); - } - - public String displayName(Integer i) { - return i.toString(); - } - }); - } - } - - return lookup; - } -} diff --git a/csl.api/src/org/netbeans/modules/csl/core/SelectCodeElementAction.java b/csl.api/src/org/netbeans/modules/csl/core/SelectCodeElementAction.java --- a/csl.api/src/org/netbeans/modules/csl/core/SelectCodeElementAction.java +++ b/csl.api/src/org/netbeans/modules/csl/core/SelectCodeElementAction.java @@ -105,14 +105,14 @@ if (name == null) return null; String shortDesc; try { - shortDesc = NbBundle.getBundle(GsfEditorKitFactory.class).getString(name); // NOI18N + shortDesc = NbBundle.getBundle(SelectCodeElementAction.class).getString(name); // NOI18N }catch (MissingResourceException mre){ shortDesc = name; } return shortDesc; } - public void actionPerformed(ActionEvent evt, JTextComponent target) { + public @Override void actionPerformed(ActionEvent evt, JTextComponent target) { if (target != null) { int selectionStartOffset = target.getSelectionStart(); int selectionEndOffset = target.getSelectionEnd(); @@ -181,7 +181,7 @@ ignoreNextCaretUpdate = true; } - public void caretUpdate(CaretEvent e) { + public @Override void caretUpdate(CaretEvent e) { if (!ignoreNextCaretUpdate) { synchronized (this) { selectionInfos = null; @@ -194,7 +194,7 @@ public void cancel() { } - public void run (ResultIterator resultIterator) throws ParseException { + public @Override void run (ResultIterator resultIterator) throws ParseException { Parser.Result parserResult = resultIterator.getParserResult (target.getCaretPosition ()); if(!(parserResult instanceof ParserResult)) { return ; @@ -256,7 +256,7 @@ return selIndex; } - public void run() { + public @Override void run() { if (selIndex == -1) { // Try to figure out the selected AST index based on the editor selection selIndex = computeSelIndex(true); diff --git a/csl.api/test/unit/src/org/netbeans/modules/csl/api/test/CslTestBase.java b/csl.api/test/unit/src/org/netbeans/modules/csl/api/test/CslTestBase.java --- a/csl.api/test/unit/src/org/netbeans/modules/csl/api/test/CslTestBase.java +++ b/csl.api/test/unit/src/org/netbeans/modules/csl/api/test/CslTestBase.java @@ -160,7 +160,7 @@ import org.netbeans.modules.csl.api.OffsetRange; import org.netbeans.modules.csl.api.PreviewableFix; import org.netbeans.modules.csl.api.Severity; -import org.netbeans.modules.csl.core.GsfEditorKitFactory; +import org.netbeans.modules.csl.core.CslEditorKit; import org.netbeans.modules.csl.core.GsfIndentTaskFactory; import org.netbeans.modules.csl.core.GsfReformatTaskFactory; import org.netbeans.modules.csl.core.LanguageRegistry; @@ -2068,8 +2068,7 @@ org.netbeans.modules.csl.core.Language language = LanguageRegistry.getInstance().getLanguageByMimeType(mimeType); assertNotNull(language); if (!language.useCustomEditorKit()) { - GsfEditorKitFactory factory = new GsfEditorKitFactory(language); - return factory.kit(); + return new CslEditorKit(mimeType); } fail("Must override getEditorKit() for useCustomEditorKit languages"); return null; diff --git a/css.editor/src/org/netbeans/modules/css/resources/layer.xml b/css.editor/src/org/netbeans/modules/css/resources/layer.xml --- a/css.editor/src/org/netbeans/modules/css/resources/layer.xml +++ b/css.editor/src/org/netbeans/modules/css/resources/layer.xml @@ -34,7 +34,9 @@ - + + + diff --git a/groovy.editor/src/org/netbeans/modules/groovy/editor/api/parser/GroovyLanguage.java b/groovy.editor/src/org/netbeans/modules/groovy/editor/api/parser/GroovyLanguage.java --- a/groovy.editor/src/org/netbeans/modules/groovy/editor/api/parser/GroovyLanguage.java +++ b/groovy.editor/src/org/netbeans/modules/groovy/editor/api/parser/GroovyLanguage.java @@ -48,7 +48,6 @@ import org.netbeans.modules.csl.api.CodeCompletionHandler; import org.netbeans.modules.csl.api.DeclarationFinder; import org.netbeans.modules.csl.api.Formatter; -import org.netbeans.modules.csl.api.HintsProvider; import org.netbeans.modules.csl.api.IndexSearcher; import org.netbeans.modules.csl.api.InstantRenamer; import org.netbeans.modules.csl.api.KeystrokeHandler; @@ -65,10 +64,10 @@ import org.netbeans.modules.groovy.editor.api.GroovyUtils; import org.netbeans.modules.groovy.editor.api.StructureAnalyzer; import org.netbeans.modules.groovy.editor.api.completion.CompletionHandler; -import org.netbeans.modules.groovy.editor.hints.infrastructure.GroovyHintsProvider; import org.netbeans.modules.groovy.editor.api.lexer.GroovyTokenId; import org.netbeans.modules.parsing.spi.Parser; import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; /** * Language/lexing configuration for Groovy @@ -77,6 +76,7 @@ * @author Martin Adamek */ @LanguageRegistration(mimeType="text/x-groovy") +@PathRecognizerRegistration(mimeTypes="text/x-groovy", sourcePathIds=ClassPath.SOURCE, libraryPathIds={}, binaryLibraryPathIds={}) //NOI18N public class GroovyLanguage extends DefaultLanguageConfig { public GroovyLanguage() { diff --git a/groovy.gsp/src/org/netbeans/modules/groovy/gsp/GspLanguage.java b/groovy.gsp/src/org/netbeans/modules/groovy/gsp/GspLanguage.java --- a/groovy.gsp/src/org/netbeans/modules/groovy/gsp/GspLanguage.java +++ b/groovy.gsp/src/org/netbeans/modules/groovy/gsp/GspLanguage.java @@ -42,18 +42,10 @@ package org.netbeans.modules.groovy.gsp; import org.netbeans.api.lexer.Language; -import org.netbeans.modules.csl.api.CodeCompletionHandler; -import org.netbeans.modules.csl.api.DeclarationFinder; -import org.netbeans.modules.csl.api.Formatter; -import org.netbeans.modules.csl.api.HintsProvider; -import org.netbeans.modules.csl.api.InstantRenamer; -import org.netbeans.modules.csl.api.KeystrokeHandler; -import org.netbeans.modules.csl.api.OccurrencesFinder; import org.netbeans.modules.csl.api.SemanticAnalyzer; import org.netbeans.modules.csl.api.StructureScanner; import org.netbeans.modules.csl.spi.DefaultLanguageConfig; import org.netbeans.modules.csl.spi.LanguageRegistration; -import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory; import org.netbeans.modules.groovy.editor.api.GroovyUtils; import org.netbeans.modules.groovy.gsp.lexer.GspTokenId; import org.netbeans.modules.parsing.spi.Parser; @@ -97,52 +89,6 @@ } @Override - public CodeCompletionHandler getCompletionHandler() { - return null; - } - - @Override - public DeclarationFinder getDeclarationFinder() { - return null; - } - - @Override - public boolean hasFormatter() { - return false; - } - - @Override - public Formatter getFormatter() { - return null; - } - - @Override - public EmbeddingIndexerFactory getIndexerFactory() { - return null; - } - - - @Override - public InstantRenamer getInstantRenamer() { - return null; - } - - @Override - public KeystrokeHandler getKeystrokeHandler() { - return null; - } - - @Override - public boolean hasOccurrencesFinder() { - return false; - } - - @Override - public OccurrencesFinder getOccurrencesFinder() { - return null; - } - - @Override public Parser getParser() { return new GspParser(); } @@ -162,13 +108,4 @@ return new GspStructureScanner(); } - @Override - public boolean hasHintsProvider() { - return false; - } - - @Override - public HintsProvider getHintsProvider() { - return null; - } } diff --git a/groovy.gsp/src/org/netbeans/modules/groovy/gsp/editor/GspKit.java b/groovy.gsp/src/org/netbeans/modules/groovy/gsp/editor/GspKit.java --- a/groovy.gsp/src/org/netbeans/modules/groovy/gsp/editor/GspKit.java +++ b/groovy.gsp/src/org/netbeans/modules/groovy/gsp/editor/GspKit.java @@ -58,7 +58,6 @@ import org.netbeans.editor.ext.ExtKit.ExtDefaultKeyTypedAction; import org.netbeans.modules.csl.core.DeleteToNextCamelCasePosition; import org.netbeans.modules.csl.core.DeleteToPreviousCamelCasePosition; -import org.netbeans.modules.csl.core.GsfEditorKitFactory; import org.netbeans.modules.csl.core.NextCamelCasePosition; import org.netbeans.modules.csl.core.PreviousCamelCasePosition; import org.netbeans.modules.csl.core.SelectCodeElementAction; @@ -116,16 +115,25 @@ // new GspToggleCommentAction(), new SelectCodeElementAction(SelectCodeElementAction.selectNextElementAction, true), new SelectCodeElementAction(SelectCodeElementAction.selectPreviousElementAction, false), - new NextCamelCasePosition(GsfEditorKitFactory.findAction(superActions, nextWordAction)), - new PreviousCamelCasePosition(GsfEditorKitFactory.findAction(superActions, previousWordAction)), - new SelectNextCamelCasePosition(GsfEditorKitFactory.findAction(superActions, selectionNextWordAction)), - new SelectPreviousCamelCasePosition(GsfEditorKitFactory.findAction(superActions, selectionPreviousWordAction)), - new DeleteToNextCamelCasePosition(GsfEditorKitFactory.findAction(superActions, removeNextWordAction)), - new DeleteToPreviousCamelCasePosition(GsfEditorKitFactory.findAction(superActions, removePreviousWordAction)), + new NextCamelCasePosition(findAction(superActions, nextWordAction)), + new PreviousCamelCasePosition(findAction(superActions, previousWordAction)), + new SelectNextCamelCasePosition(findAction(superActions, selectionNextWordAction)), + new SelectPreviousCamelCasePosition(findAction(superActions, selectionPreviousWordAction)), + new DeleteToNextCamelCasePosition(findAction(superActions, removeNextWordAction)), + new DeleteToPreviousCamelCasePosition(findAction(superActions, removePreviousWordAction)), new InstantRenameAction(), }); } + private static Action findAction(Action [] actions, String name) { + for(Action a : actions) { + Object nameObj = a.getValue(Action.NAME); + if (nameObj instanceof String && name.equals(nameObj)) { + return a; + } + } + return null; + } private boolean handleDeletion(BaseDocument doc, int dotPos) { if (dotPos > 0) { try { diff --git a/groovy.gsp/src/org/netbeans/modules/groovy/gsp/resources/layer.xml b/groovy.gsp/src/org/netbeans/modules/groovy/gsp/resources/layer.xml --- a/groovy.gsp/src/org/netbeans/modules/groovy/gsp/resources/layer.xml +++ b/groovy.gsp/src/org/netbeans/modules/groovy/gsp/resources/layer.xml @@ -97,12 +97,22 @@ - + + + - - - - + + + + + + + + + + + + diff --git a/html.editor/src/org/netbeans/modules/html/editor/resources/layer.xml b/html.editor/src/org/netbeans/modules/html/editor/resources/layer.xml --- a/html.editor/src/org/netbeans/modules/html/editor/resources/layer.xml +++ b/html.editor/src/org/netbeans/modules/html/editor/resources/layer.xml @@ -95,7 +95,9 @@ - + + + @@ -105,9 +107,15 @@ - - - + + + + + + + + + @@ -208,8 +216,12 @@ - - + + + + + + @@ -235,7 +247,9 @@ - + + + diff --git a/javascript.editing/src/org/netbeans/modules/javascript/editing/JsLanguage.java b/javascript.editing/src/org/netbeans/modules/javascript/editing/JsLanguage.java --- a/javascript.editing/src/org/netbeans/modules/javascript/editing/JsLanguage.java +++ b/javascript.editing/src/org/netbeans/modules/javascript/editing/JsLanguage.java @@ -60,6 +60,7 @@ import org.netbeans.modules.javascript.editing.lexer.JsTokenId; import org.netbeans.modules.parsing.spi.Parser; import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; /* @@ -68,6 +69,7 @@ * @author Tor Norbye */ @LanguageRegistration(mimeType="text/javascript") //NOI18N +@PathRecognizerRegistration(mimeTypes="text/javascript", libraryPathIds=JsClassPathProvider.BOOT_CP, binaryLibraryPathIds={}) public class JsLanguage extends DefaultLanguageConfig { private static boolean jsClassPathRegistered = false; diff --git a/javascript.editing/src/org/netbeans/modules/javascript/editing/JsonLanguage.java b/javascript.editing/src/org/netbeans/modules/javascript/editing/JsonLanguage.java --- a/javascript.editing/src/org/netbeans/modules/javascript/editing/JsonLanguage.java +++ b/javascript.editing/src/org/netbeans/modules/javascript/editing/JsonLanguage.java @@ -53,6 +53,7 @@ import org.netbeans.modules.csl.spi.LanguageRegistration; import org.netbeans.modules.javascript.editing.lexer.JsTokenId; import org.netbeans.modules.parsing.spi.Parser; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; /** * Configuration for JSON @@ -60,6 +61,7 @@ * @author Tor Norbye */ @LanguageRegistration(mimeType="text/x-json") //NOI18N +@PathRecognizerRegistration(mimeTypes="text/x-json", libraryPathIds=JsClassPathProvider.BOOT_CP, binaryLibraryPathIds={}) public class JsonLanguage extends DefaultLanguageConfig { public JsonLanguage() { diff --git a/languages.yaml/src/org/netbeans/modules/languages/yaml/layer.xml b/languages.yaml/src/org/netbeans/modules/languages/yaml/layer.xml --- a/languages.yaml/src/org/netbeans/modules/languages/yaml/layer.xml +++ b/languages.yaml/src/org/netbeans/modules/languages/yaml/layer.xml @@ -64,7 +64,9 @@ - + + + diff --git a/parsing.api/apichanges.xml b/parsing.api/apichanges.xml --- a/parsing.api/apichanges.xml +++ b/parsing.api/apichanges.xml @@ -107,6 +107,21 @@ + + + Adding PathRecognizerRegistration annotation + + + + + +

+ Added PathRecognizerRegistration annotation that simplyfies registering PathRecognizers. +

+
+ + +
Adding ErrorsCache diff --git a/parsing.api/nbproject/project.properties b/parsing.api/nbproject/project.properties --- a/parsing.api/nbproject/project.properties +++ b/parsing.api/nbproject/project.properties @@ -2,4 +2,4 @@ javac.source=1.6 javadoc.apichanges=${basedir}/apichanges.xml javadoc.arch=${basedir}/arch.xml -spec.version.base=1.31.0 +spec.version.base=1.32.0 diff --git a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/DefaultPathRecognizer.java b/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/DefaultPathRecognizer.java new file mode 100644 --- /dev/null +++ b/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/DefaultPathRecognizer.java @@ -0,0 +1,165 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.parsing.impl.indexing; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.netbeans.api.editor.mimelookup.MimePath; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizer; + +/** + * + * @author vita + */ +public final class DefaultPathRecognizer extends PathRecognizer { + + // ------------------------------------------------------------------------ + // PathRecognizer implementation + // ------------------------------------------------------------------------ + + @Override + public Set getSourcePathIds() { + return sourcePathIds; + } + + @Override + public Set getBinaryLibraryPathIds() { + return binaryLibraryPathIds; + } + + @Override + public Set getLibraryPathIds() { + return libraryPathIds; + } + + @Override + public Set getMimeTypes() { + return mimeTypes; + } + + // ------------------------------------------------------------------------ + // Public implementation + // ------------------------------------------------------------------------ + + public static PathRecognizer createInstance(Map fileAttributes) { + + // path ids + Set sourcePathIds = readIdsAttribute(fileAttributes, "sourcePathIds"); //NOI18N + Set libraryPathIds = readIdsAttribute(fileAttributes, "libraryPathIds"); //NOI18N + Set binaryLibraryPathIds = readIdsAttribute(fileAttributes, "binaryLibraryPathIds"); //NOI18N + + // mime types + Set mimeTypes = new HashSet(); + Object mts = fileAttributes.get("mimeTypes"); //NOI18N + if (mts instanceof String) { + String [] arr = ((String) mts).split(","); //NOI18N + for(String mt : arr) { + mt = mt.trim(); + if (mt.length() > 0 && MimePath.validate(mt)) { + mimeTypes.add(mt); + } else { + LOG.log(Level.WARNING, "Invalid mimetype {0}, ignoring.", mt); //NOI18N + } + } + } + + return new DefaultPathRecognizer(sourcePathIds, libraryPathIds, binaryLibraryPathIds, Collections.unmodifiableSet(mimeTypes)); + } + + @Override + public String toString() { + return super.toString() + + "[sourcePathIds=" + sourcePathIds //NOI18N + + ", libraryPathIds=" + libraryPathIds //NOI18N + + ", binaryLibraryPathIds=" + binaryLibraryPathIds //NOI18N + + ", mimeTypes=" + mimeTypes; //NOI18N + } + + // ------------------------------------------------------------------------ + // Private implementation + // ------------------------------------------------------------------------ + + private static final Logger LOG = Logger.getLogger(DefaultPathRecognizer.class.getName()); + + private final Set sourcePathIds; + private final Set libraryPathIds; + private final Set binaryLibraryPathIds; + private final Set mimeTypes; + + private DefaultPathRecognizer(Set sourcePathIds, Set libraryPathIds, Set binaryLibraryPathIds, Set mimeTypes) { + this.sourcePathIds = sourcePathIds; + this.libraryPathIds = libraryPathIds; + this.binaryLibraryPathIds = binaryLibraryPathIds; + this.mimeTypes = mimeTypes; + } + + private static Set readIdsAttribute(Map fileAttributes, String attributeName) { + Set ids = new HashSet(); + + Object attributeValue = fileAttributes.get(attributeName); //NOI18N + if (attributeValue instanceof String) { + String [] varr = ((String) attributeValue).split(","); //NOI18N + for(String v : varr) { + v = v.trim(); + if (v.equals("ANY")) { //NOI18N + ids = null; + break; + } else if (v.length() > 0) { + ids.add(v); + } else { + LOG.log(Level.WARNING, "Empty IDs are not alowed in {0} attribute, ignoring.", attributeName); //NOI18N + } + } + } else { + if (attributeValue != null) { + LOG.log(Level.WARNING, "Invalid {0} attribute value, expecting java.lang.String, but got {1}, {2}", //NOI18N + new Object [] { attributeName, attributeValue, attributeValue == null ? null : attributeValue.getClass()}); + } + + ids = Collections.emptySet(); + } + + return ids == null ? null : Collections.unmodifiableSet(ids); + } +} diff --git a/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/PathRecognizerRegistrationProcessor.java b/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/PathRecognizerRegistrationProcessor.java new file mode 100644 --- /dev/null +++ b/parsing.api/src/org/netbeans/modules/parsing/impl/indexing/PathRecognizerRegistrationProcessor.java @@ -0,0 +1,195 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2010 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.parsing.impl.indexing; + +import java.util.Set; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizer; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; +import org.openide.filesystems.annotations.LayerBuilder; +import org.openide.filesystems.annotations.LayerBuilder.File; +import org.openide.filesystems.annotations.LayerGeneratingProcessor; +import org.openide.filesystems.annotations.LayerGenerationException; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author Vita Stejskal + */ +@ServiceProvider(service=Processor.class) +@SupportedAnnotationTypes("org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration") //NOI18N +@SupportedSourceVersion(SourceVersion.RELEASE_6) +public class PathRecognizerRegistrationProcessor extends LayerGeneratingProcessor { + + @Override + protected boolean handleProcess(Set annotations, RoundEnvironment roundEnv) throws LayerGenerationException { + for(Element e : roundEnv.getElementsAnnotatedWith(PathRecognizerRegistration.class)) { + TypeElement cls = (TypeElement) e; + PathRecognizerRegistration prr = cls.getAnnotation(PathRecognizerRegistration.class); + + String sourcePathIds = processIds(prr.sourcePathIds()); + String libraryPathIds = processIds(prr.libraryPathIds()); + String binaryLibraryPathIds = processIds(prr.binaryLibraryPathIds()); + String mimeTypes = processMts(prr.mimeTypes()); + + if (mimeTypes != null && (sourcePathIds != null || libraryPathIds != null || binaryLibraryPathIds != null)) { + final LayerBuilder lb = layer(cls); + File f = instanceFile(lb, + "Services/Hidden/PathRecognizers", //NOI18N + makeFilesystemName(cls.getQualifiedName().toString()), + DefaultPathRecognizer.class, + "createInstance", //NOI18N + PathRecognizer.class); + + if (sourcePathIds != null) { + f.stringvalue("sourcePathIds", sourcePathIds); //NOI18N + } + if (libraryPathIds != null) { + f.stringvalue("libraryPathIds", libraryPathIds); //NOI18N + } + if (binaryLibraryPathIds != null) { + f.stringvalue("binaryLibraryPathIds", binaryLibraryPathIds); //NOI18N + } + if (mimeTypes != null) { + f.stringvalue("mimeTypes", mimeTypes); //NOI18N + } + + f.write(); + } + } + return true; + } + + private static String processIds(String [] ids) { + if (ids.length == 0) { + return null; + } else if (ids.length == 1 && ids[0].equals("ANY")) { + return "ANY"; //NOI18N + } else { + StringBuilder sb = new StringBuilder(); + for(String s : ids) { + if (s == null) { + continue; + } + + s = s.trim(); + if (s.length() == 0 || s.equals("ANY")) { + continue; + } + + if (sb.length() > 0) { + sb.append(','); //NOI18N + } + sb.append(s); + } + return sb.length() > 0 ? sb.toString() : null; + } + } + + private static String processMts(String [] mts) { + if (mts == null || mts.length == 0) { + return null; + } else { + StringBuilder sb = new StringBuilder(); + for(String s : mts) { + if (s == null) { + continue; + } + + s = s.trim(); + if (s.length() == 0) { + continue; + } + + if (sb.length() > 0) { + sb.append(','); //NOI18N + } + sb.append(s); + } + return sb.length() > 0 ? sb.toString() : null; + } + } + + private static File instanceFile(LayerBuilder b, String folder, String name, Class implClass, String factoryMethod, Class... instanceOf) { + String basename; + if (name == null) { + basename = implClass.getName().replace('.', '-'); //NOI18N + if (factoryMethod != null) { + basename += "-" + factoryMethod; //NOI18N + } + } else { + basename = name; + } + + File f = b.file(folder + "/" + basename + ".instance"); //NOI18N + if (implClass != null) { + if (factoryMethod != null) { + f.methodvalue("instanceCreate", implClass.getName(), factoryMethod); //NOI18N + } else { + f.stringvalue("instanceClass", implClass.getName()); //NOI18N + } + } + + for(Class c : instanceOf) { + f.stringvalue("instanceOf", c.getName()); //NOI18N + } + + return f; + } + + private static String makeFilesystemName(String s) { + StringBuilder sb = new StringBuilder(s.length()); + for(int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (Character.isLetterOrDigit(c)) { + sb.append(c); + } else { + sb.append("-"); //NOI18N + } + } + return sb.toString(); + } +} diff --git a/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/PathRecognizerRegistration.java b/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/PathRecognizerRegistration.java new file mode 100644 --- /dev/null +++ b/parsing.api/src/org/netbeans/modules/parsing/spi/indexing/PathRecognizerRegistration.java @@ -0,0 +1,96 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2010 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.parsing.spi.indexing; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.netbeans.api.java.classpath.GlobalPathRegistry; + +/** + * Registers a PathRecognizer in the default Lookup. + * + *

+ * This annotation can be added to any type, but typically you should add it to an + * indexer factory or a CSL language definition. + * + * @author Vita Stejskal + * @since 1.32 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.SOURCE) +public @interface PathRecognizerRegistration { + + /** + * Gets classpath IDs for source paths registered in + * the {@link GlobalPathRegistry}. + * + * @return The list of source path IDs; "ANY" means any source path ID + * and an empty array ({}) means no source path ID. + */ + public String [] sourcePathIds() default "ANY"; //NOI18N + + /** + * Gets classpath IDs for library paths registered in + * the {@link GlobalPathRegistry}. + * + * @return The list of source path IDs; "ANY" means any source path ID + * and an empty array ({}) means no source path ID. + */ + public String [] libraryPathIds() default "ANY"; //NOI18N + + /** + * Gets classpath IDs for binray library paths registered in + * the {@link GlobalPathRegistry}. + * + * @return The list of source path IDs; "ANY" means any source path ID + * and an empty array ({}) means no source path ID. + */ + public String [] binaryLibraryPathIds() default "ANY"; //NOI18N + + /** + * Gets mime types of files relevant for the paths identified by the other methods. + * + * @return The list of mime types; null, an empty array ({}) + * and empty strings ("") are ignored. + */ + public String [] mimeTypes() default {}; +} diff --git a/php.editor/src/org/netbeans/modules/php/editor/PHPLanguage.java b/php.editor/src/org/netbeans/modules/php/editor/PHPLanguage.java --- a/php.editor/src/org/netbeans/modules/php/editor/PHPLanguage.java +++ b/php.editor/src/org/netbeans/modules/php/editor/PHPLanguage.java @@ -56,6 +56,7 @@ import org.netbeans.modules.csl.spi.LanguageRegistration; import org.netbeans.modules.parsing.spi.Parser; import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; import org.netbeans.modules.php.editor.indent.PHPBracketCompleter; import org.netbeans.modules.php.editor.indent.PHPFormatter; import org.netbeans.modules.php.editor.index.PHPIndexer; @@ -75,6 +76,7 @@ * @author Petr Pisl */ @LanguageRegistration(mimeType="text/x-php5") //NOI18N +@PathRecognizerRegistration(mimeTypes="text/x-php5", sourcePathIds=PhpSourcePath.SOURCE_CP, libraryPathIds=PhpSourcePath.BOOT_CP, binaryLibraryPathIds={}) //NOI18N public class PHPLanguage extends DefaultLanguageConfig { @Override diff --git a/php.editor/src/org/netbeans/modules/php/editor/resources/layer.xml b/php.editor/src/org/netbeans/modules/php/editor/resources/layer.xml --- a/php.editor/src/org/netbeans/modules/php/editor/resources/layer.xml +++ b/php.editor/src/org/netbeans/modules/php/editor/resources/layer.xml @@ -41,8 +41,12 @@ - - + + + + + + diff --git a/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/RhtmlLanguage.java b/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/RhtmlLanguage.java --- a/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/RhtmlLanguage.java +++ b/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/RhtmlLanguage.java @@ -51,11 +51,13 @@ import org.netbeans.modules.csl.spi.DefaultLanguageConfig; import org.netbeans.modules.csl.spi.LanguageRegistration; import org.netbeans.modules.parsing.spi.Parser; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; import org.netbeans.modules.ruby.RubyIndexer; import org.netbeans.modules.ruby.RubyStructureAnalyzer; import org.netbeans.modules.ruby.RubyUtils; @LanguageRegistration(mimeType="application/x-httpd-eruby", useCustomEditorKit=true) //NOI18N +@PathRecognizerRegistration(mimeTypes="application/x-httpd-eruby", sourcePathIds=RubyLanguage.SOURCE, libraryPathIds=RubyLanguage.BOOT, binaryLibraryPathIds={}) //NOI18N public class RhtmlLanguage extends DefaultLanguageConfig { public RhtmlLanguage() { diff --git a/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/editor/RhtmlKit.java b/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/editor/RhtmlKit.java --- a/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/editor/RhtmlKit.java +++ b/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/editor/RhtmlKit.java @@ -62,7 +62,6 @@ import org.netbeans.lib.editor.util.swing.DocumentUtilities; import org.netbeans.modules.csl.core.DeleteToNextCamelCasePosition; import org.netbeans.modules.csl.core.DeleteToPreviousCamelCasePosition; -import org.netbeans.modules.csl.core.GsfEditorKitFactory; import org.netbeans.modules.csl.core.NextCamelCasePosition; import org.netbeans.modules.csl.core.PreviousCamelCasePosition; import org.netbeans.modules.csl.core.SelectCodeElementAction; @@ -74,7 +73,6 @@ import org.netbeans.modules.ruby.lexer.RubyTokenId; import org.netbeans.modules.ruby.rhtml.lexer.api.RhtmlTokenId; import org.netbeans.modules.ruby.rhtml.spi.DtdResolver; -import org.openide.util.Exceptions; import org.openide.util.Lookup; /** @@ -155,16 +153,26 @@ new RhtmlToggleCommentAction(), new SelectCodeElementAction(SelectCodeElementAction.selectNextElementAction, true), new SelectCodeElementAction(SelectCodeElementAction.selectPreviousElementAction, false), - new NextCamelCasePosition(GsfEditorKitFactory.findAction(superActions, nextWordAction)), - new PreviousCamelCasePosition(GsfEditorKitFactory.findAction(superActions, previousWordAction)), - new SelectNextCamelCasePosition(GsfEditorKitFactory.findAction(superActions, selectionNextWordAction)), - new SelectPreviousCamelCasePosition(GsfEditorKitFactory.findAction(superActions, selectionPreviousWordAction)), - new DeleteToNextCamelCasePosition(GsfEditorKitFactory.findAction(superActions, removeNextWordAction)), - new DeleteToPreviousCamelCasePosition(GsfEditorKitFactory.findAction(superActions, removePreviousWordAction)), + new NextCamelCasePosition(findAction(superActions, nextWordAction)), + new PreviousCamelCasePosition(findAction(superActions, previousWordAction)), + new SelectNextCamelCasePosition(findAction(superActions, selectionNextWordAction)), + new SelectPreviousCamelCasePosition(findAction(superActions, selectionPreviousWordAction)), + new DeleteToNextCamelCasePosition(findAction(superActions, removeNextWordAction)), + new DeleteToPreviousCamelCasePosition(findAction(superActions, removePreviousWordAction)), new InstantRenameAction(), }); } + private static Action findAction(Action [] actions, String name) { + for(Action a : actions) { + Object nameObj = a.getValue(Action.NAME); + if (nameObj instanceof String && name.equals(nameObj)) { + return a; + } + } + return null; + } + private boolean handleDeletion(BaseDocument doc, int dotPos) { if (dotPos > 0) { try { diff --git a/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/resources/layer.xml b/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/resources/layer.xml --- a/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/resources/layer.xml +++ b/ruby.rhtml/src/org/netbeans/modules/ruby/rhtml/resources/layer.xml @@ -108,13 +108,25 @@ - - + + + + + + - - - - + + + + + + + + + + + + diff --git a/ruby/src/org/netbeans/modules/ruby/RubyLanguage.java b/ruby/src/org/netbeans/modules/ruby/RubyLanguage.java --- a/ruby/src/org/netbeans/modules/ruby/RubyLanguage.java +++ b/ruby/src/org/netbeans/modules/ruby/RubyLanguage.java @@ -56,6 +56,7 @@ import org.netbeans.modules.csl.spi.LanguageRegistration; import org.netbeans.modules.parsing.spi.Parser; import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory; +import org.netbeans.modules.parsing.spi.indexing.PathRecognizerRegistration; import org.netbeans.modules.ruby.lexer.RubyTokenId; /* @@ -64,6 +65,7 @@ * @author Tor Norbye */ @LanguageRegistration(mimeType="text/x-ruby") +@PathRecognizerRegistration(mimeTypes="text/x-ruby", sourcePathIds=RubyLanguage.SOURCE, libraryPathIds=RubyLanguage.BOOT, binaryLibraryPathIds={}) //NOI18N public class RubyLanguage extends DefaultLanguageConfig { public final static String BOOT = "ruby/classpath/boot"; diff --git a/web.core.syntax/src/org/netbeans/modules/web/core/syntax/resources/layer.xml b/web.core.syntax/src/org/netbeans/modules/web/core/syntax/resources/layer.xml --- a/web.core.syntax/src/org/netbeans/modules/web/core/syntax/resources/layer.xml +++ b/web.core.syntax/src/org/netbeans/modules/web/core/syntax/resources/layer.xml @@ -54,7 +54,9 @@ - + + + @@ -90,10 +92,18 @@ - - - - + + + + + + + + + + + + @@ -179,12 +189,20 @@ - - - + + + + + + + + + - + + + @@ -208,10 +226,18 @@ - - - - + + + + + + + + + + + + @@ -285,8 +311,12 @@ - - + + + + + +