| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.javascript2.extjs; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import org.netbeans.api.lexer.Token; |
| import org.netbeans.api.lexer.TokenHierarchy; |
| import org.netbeans.api.lexer.TokenSequence; |
| import org.netbeans.modules.csl.api.CodeCompletionContext; |
| import org.netbeans.modules.csl.api.CompletionProposal; |
| import org.netbeans.modules.csl.api.ElementHandle; |
| import org.netbeans.modules.csl.spi.ParserResult; |
| import org.netbeans.modules.javascript2.lexer.api.JsTokenId; |
| import org.netbeans.modules.javascript2.lexer.api.LexUtilities; |
| import org.netbeans.modules.javascript2.editor.spi.CompletionContext; |
| import org.netbeans.modules.javascript2.editor.spi.CompletionProvider; |
| import org.openide.modules.InstalledFileLocator; |
| |
| /** |
| * |
| * @author Petr Pisl |
| */ |
| @CompletionProvider.Registration(priority=11) |
| public class ExtJsCodeCompletion implements CompletionProvider { |
| |
| private static final String FILE_LOCATION = "docs/extjs-properties.xml"; //NOI18N |
| private static File extPropertyFile; |
| |
| private static synchronized File getDataFile() { |
| if (extPropertyFile == null) { |
| extPropertyFile = InstalledFileLocator.getDefault().locate(FILE_LOCATION, "org.netbeans.modules.javascript2.extjs", false); //NOI18N |
| } |
| return extPropertyFile; |
| } |
| |
| |
| private static HashMap<String, Collection<ExtJsDataItem>> ccData = null; |
| |
| private static synchronized Map<String, Collection<ExtJsDataItem>> getData() { |
| return DataLoader.getData(getDataFile()); |
| } |
| |
| @Override |
| public List<CompletionProposal> complete(CodeCompletionContext ccContext, CompletionContext jsCompletionContext, String prefix) { |
| if (jsCompletionContext != CompletionContext.OBJECT_PROPERTY_NAME) { |
| return Collections.<CompletionProposal>emptyList(); |
| } |
| // find the object that can be configured |
| TokenHierarchy<?> th = ccContext.getParserResult().getSnapshot().getTokenHierarchy(); |
| if (th == null) { |
| return Collections.<CompletionProposal>emptyList(); |
| } |
| int carretOffset = ccContext.getCaretOffset(); |
| int eOffset = ccContext.getParserResult().getSnapshot().getEmbeddedOffset(carretOffset); |
| TokenSequence<? extends JsTokenId> ts = LexUtilities.getJsTokenSequence(th, eOffset); |
| if (ts == null) { |
| return Collections.<CompletionProposal>emptyList(); |
| } |
| |
| ts.move(eOffset); |
| |
| if (!ts.moveNext() && !ts.movePrevious()){ |
| return Collections.<CompletionProposal>emptyList(); |
| } |
| |
| Token<? extends JsTokenId> token = null; |
| JsTokenId tokenId; |
| //find the begining of the object literal |
| int balance = 1; |
| while (ts.movePrevious() && balance > 0) { |
| token = ts.token(); |
| tokenId = token.id(); |
| if (tokenId == JsTokenId.BRACKET_RIGHT_CURLY) { |
| balance++; |
| } else if (tokenId == JsTokenId.BRACKET_LEFT_CURLY) { |
| balance--; |
| } |
| } |
| if (token == null || balance != 0) { |
| return Collections.<CompletionProposal>emptyList(); |
| } |
| |
| // now we should be at the beginning of the object literal. |
| token = LexUtilities.findPreviousToken(ts, Arrays.asList(JsTokenId.IDENTIFIER)); |
| tokenId = token.id(); |
| StringBuilder sb = new StringBuilder(token.text()); |
| while ((tokenId == JsTokenId.IDENTIFIER || tokenId == JsTokenId.OPERATOR_DOT) && ts.movePrevious()) { |
| token = ts.token(); tokenId = token.id(); |
| if (tokenId == JsTokenId.OPERATOR_DOT) { |
| sb.insert(0, '.'); // NOI18N |
| } else if (tokenId == JsTokenId.IDENTIFIER) { |
| sb.insert(0, token.text()); |
| } |
| } |
| |
| String fqn = sb.toString(); |
| Map<String, Collection<ExtJsDataItem>> data = getData(); |
| Collection<ExtJsDataItem> items = data.get(fqn); |
| int anchorOffset = eOffset - ccContext.getPrefix().length(); |
| if (items != null) { |
| List<CompletionProposal> result = new ArrayList<CompletionProposal>(); |
| for (ExtJsDataItem item : items) { |
| if (item.getName().startsWith(prefix)) { |
| result.add(ExtJsCompletionItem.createExtJsItem(item, anchorOffset)); |
| } |
| } |
| return result; |
| } |
| return Collections.<CompletionProposal>emptyList(); |
| } |
| |
| @Override |
| public String getHelpDocumentation(ParserResult info, ElementHandle element) { |
| if (element != null && element instanceof ExtJsElement) { |
| return ((ExtJsElement)element).getDocumentation(); |
| } |
| return null; |
| } |
| |
| } |