blob: be1612c3211f256209ea42b0b863694d2f664f38 [file] [log] [blame]
/*
* 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.model.spi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.modules.csl.api.Documentation;
import org.netbeans.modules.csl.api.ElementHandle;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.csl.api.Modifier;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.spi.ParserResult;
import org.netbeans.modules.javascript2.model.JsArrayReference;
import org.netbeans.modules.javascript2.model.JsFunctionImpl;
import org.netbeans.modules.javascript2.model.JsFunctionReference;
import org.netbeans.modules.javascript2.model.JsObjectImpl;
import org.netbeans.modules.javascript2.model.JsObjectReference;
import org.netbeans.modules.javascript2.model.ModelElementFactoryAccessor;
import org.netbeans.modules.javascript2.model.api.JsArray;
import org.netbeans.modules.javascript2.model.api.JsElement;
import org.netbeans.modules.javascript2.model.api.JsElement.Kind;
import org.netbeans.modules.javascript2.model.api.JsFunction;
import org.netbeans.modules.javascript2.model.api.JsObject;
import org.netbeans.modules.javascript2.model.api.Model;
import org.netbeans.modules.javascript2.model.api.Occurrence;
import org.netbeans.modules.javascript2.types.api.DeclarationScope;
import org.netbeans.modules.javascript2.types.api.Identifier;
import org.netbeans.modules.javascript2.types.api.TypeUsage;
import org.openide.filesystems.FileObject;
/**
*
* @author Petr Hejl
*/
public final class ModelElementFactory {
static {
ModelElementFactoryAccessor.setDefault(new ModelElementFactoryAccessor() {
@Override
public ModelElementFactory createModelElementFactory() {
return new ModelElementFactory();
}
});
}
private ModelElementFactory() {
super();
}
public JsFunction newGlobalObject(FileObject fileObject, int length) {
return JsFunctionImpl.createGlobal(fileObject, length, null);
}
public JsObject loadGlobalObject(FileObject fileObject, int length,
String sourceLabel, URL defaultDocURL) throws IOException {
InputStream is = fileObject.getInputStream();
try {
return loadGlobalObject(is, sourceLabel, defaultDocURL);
} finally {
is.close();
}
}
public JsObject loadGlobalObject(InputStream is, String sourceLabel, URL defaultDocURL) throws IOException {
JsFunction global = newGlobalObject(null, Integer.MAX_VALUE);
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); // NOI18N
try {
for (JsObject object : Model.readModel(reader, global, sourceLabel, defaultDocURL)) {
putGlobalProperty(global, object);
}
return global;
} finally {
reader.close();
}
}
public JsObject putGlobalProperty(JsFunction global, JsObject property) {
if (property.getParent() != global) {
throw new IllegalArgumentException("Property is not child of global");
}
JsObject wrapped;
if (property instanceof JsFunction) {
GlobalFunction real = new GlobalFunction((JsFunction) property);
real.setParentScope(global);
real.setParent(global);
wrapped = real;
} else {
GlobalObject real = new GlobalObject(property);
real.setParent(global);
wrapped = real;
}
global.addProperty(wrapped.getName(), wrapped);
return wrapped;
}
public JsObject newObject(JsObject parent, String name, OffsetRange offsetRange, boolean isDeclared) {
return newObject(parent, name, offsetRange, isDeclared, null);
}
public JsObject newObject(JsObject parent, String name, OffsetRange offsetRange, boolean isDeclared, String sourceLabel) {
return new JsObjectImpl(parent, new Identifier(name, offsetRange), offsetRange, isDeclared, null, sourceLabel);
}
public JsFunction newFunction(DeclarationScope scope, JsObject parent, String name, Collection<String> params) {
return newFunction(scope, parent, name, params, null);
}
public JsFunction newFunction(DeclarationScope scope, JsObject parent, String name, Collection<String> params, String sourceLabel) {
List<Identifier> realParams = new ArrayList<Identifier>();
for (String param : params) {
realParams.add(new Identifier(param, OffsetRange.NONE));
}
return newFunction(scope, parent, new Identifier(name, OffsetRange.NONE), realParams, OffsetRange.NONE, sourceLabel);
}
public JsFunction newFunction(DeclarationScope scope, JsObject parent, String name, Collection<String> params, OffsetRange range, String sourceLabel) {
List<Identifier> realParams = new ArrayList<Identifier>();
for (String param : params) {
realParams.add(new Identifier(param, OffsetRange.NONE));
}
return newFunction(scope, parent, new Identifier(name, OffsetRange.NONE), realParams, range, sourceLabel);
}
public JsFunction newFunction(DeclarationScope scope, JsObject parent, Identifier name, List<Identifier> params, OffsetRange range) {
return newFunction(scope, parent, name, params, range, null);
}
public JsFunction newFunction(DeclarationScope scope, JsObject parent, Identifier name, List<Identifier> params, OffsetRange range, String sourceLabel) {
return new JsFunctionImpl(scope, parent, name, params, range, null, sourceLabel);
}
public JsObject newReference(JsObject parent, String name, OffsetRange offsetRange,
JsObject original, boolean isDeclared, @NullAllowed Set<Modifier> modifiers) {
if (original instanceof JsFunction) {
return new JsFunctionReference(parent, new Identifier(name, offsetRange),
(JsFunction) original, isDeclared, modifiers);
} else if (original instanceof JsArray) {
return new JsArrayReference(parent, new Identifier(name, offsetRange),
(JsArray) original, isDeclared, modifiers);
}
return new JsObjectReference(parent, new Identifier(name, offsetRange),
original, isDeclared, modifiers);
}
public JsObject newReference(String name, JsObject original, boolean isDeclared) {
if (original instanceof JsFunction) {
return new OriginalParentFunctionReference(new Identifier(name, OffsetRange.NONE), (JsFunction) original, isDeclared);
} else if (original instanceof JsArray) {
return new OriginalParentArrayReference(new Identifier(name, OffsetRange.NONE), (JsArray) original, isDeclared);
}
return new OriginalParentObjectReference(new Identifier(name, OffsetRange.NONE), original, isDeclared);
}
public JsObject newReference(String name, JsObject original, boolean isDeclared, boolean isVirtual) {
JsObject object = newReference(name, original, isDeclared);
((JsObjectImpl)object).setVirtual(isVirtual);
return object;
}
public TypeUsage newType(String name, int offset, boolean resolved) {
return new TypeUsage(name, offset, resolved);
}
private static class OriginalParentFunctionReference extends JsFunctionReference {
public OriginalParentFunctionReference(Identifier declarationName, JsFunction original,
boolean isDeclared) {
super(original.getParent(), declarationName, original, isDeclared, null);
}
@Override
public JsObject getParent() {
return getOriginal().getParent();
}
}
private static class OriginalParentArrayReference extends JsArrayReference {
public OriginalParentArrayReference(Identifier declarationName, JsArray original,
boolean isDeclared) {
super(original.getParent(), declarationName, original, isDeclared, null);
}
@Override
public JsObject getParent() {
return getOriginal().getParent();
}
}
private static class OriginalParentObjectReference extends JsObjectReference {
public OriginalParentObjectReference(Identifier declarationName, JsObject original, boolean isDeclared) {
super(original.getParent(), declarationName, original, isDeclared, null);
}
@Override
public JsObject getParent() {
return getOriginal().getParent();
}
}
private static class GlobalObject implements JsObject {
private final JsObject delegate;
private JsObject parent;
public GlobalObject(JsObject delegate) {
this.delegate = delegate;
this.parent = delegate.getParent();
}
@Override
public JsObject getParent() {
return this.parent;
}
public void setParent(JsObject parent) {
this.parent = parent;
}
// pure delegation follows
@Override
public Identifier getDeclarationName() {
return delegate.getDeclarationName();
}
@Override
public Map<String, ? extends JsObject> getProperties() {
return delegate.getProperties();
}
@Override
public void addProperty(String name, JsObject property) {
delegate.addProperty(name, property);
}
@Override
public JsObject getProperty(String name) {
return delegate.getProperty(name);
}
@Override
public List<Occurrence> getOccurrences() {
return delegate.getOccurrences();
}
@Override
public void addOccurrence(OffsetRange offsetRange) {
delegate.addOccurrence(offsetRange);
}
@Override
public String getFullyQualifiedName() {
return delegate.getFullyQualifiedName();
}
@Override
public Collection<? extends TypeUsage> getAssignmentForOffset(int offset) {
return delegate.getAssignmentForOffset(offset);
}
@Override
public Collection<? extends TypeUsage> getAssignments() {
return delegate.getAssignments();
}
@Override
public int getAssignmentCount() {
return delegate.getAssignmentCount();
}
@Override
public void addAssignment(TypeUsage typeName, int offset) {
delegate.addAssignment(typeName, offset);
}
@Override
public void clearAssignments() {
delegate.clearAssignments();
}
@Override
public boolean isAnonymous() {
return delegate.isAnonymous();
}
@Override
public void setAnonymous(boolean value) {
delegate.setAnonymous(value);
}
@Override
public boolean isDeprecated() {
return delegate.isDeprecated();
}
@Override
public boolean hasExactName() {
return delegate.hasExactName();
}
@Override
public Documentation getDocumentation() {
return delegate.getDocumentation();
}
@Override
public void setDocumentation(Documentation documentation) {
delegate.setDocumentation(documentation);
}
@Override
public int getOffset() {
return delegate.getOffset();
}
@Override
public OffsetRange getOffsetRange() {
return delegate.getOffsetRange();
}
@Override
public Kind getJSKind() {
return delegate.getJSKind();
}
@Override
public boolean isDeclared() {
return delegate.isDeclared();
}
@Override
public String getSourceLabel() {
return delegate.getSourceLabel();
}
@Override
public boolean isPlatform() {
return delegate.isPlatform();
}
@Override
public FileObject getFileObject() {
return delegate.getFileObject();
}
@Override
public String getMimeType() {
return delegate.getMimeType();
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public String getIn() {
return delegate.getIn();
}
@Override
public ElementKind getKind() {
return delegate.getKind();
}
@Override
public Set<Modifier> getModifiers() {
return delegate.getModifiers();
}
@Override
public boolean signatureEquals(ElementHandle handle) {
return delegate.signatureEquals(handle);
}
@Override
public OffsetRange getOffsetRange(ParserResult result) {
return delegate.getOffsetRange(result);
}
@Override
public boolean containsOffset(int offset) {
return delegate.containsOffset(offset);
}
@Override
public boolean isVirtual() {
return false;
}
@Override
public boolean moveProperty(String name, JsObject newParent) {
return delegate.moveProperty(name, newParent);
}
}
private static class GlobalFunction implements JsFunction {
private final JsFunction delegate;
private DeclarationScope inScope;
private JsObject parent;
public GlobalFunction(JsFunction delegate) {
this.delegate = delegate;
this.inScope = delegate.getParentScope();
this.parent = delegate.getParent();
}
@Override
public DeclarationScope getParentScope() {
return this.inScope;
}
protected void setParentScope(DeclarationScope inScope) {
this.inScope = inScope;
}
@Override
public JsObject getParent() {
return this.parent;
}
public void setParent(JsObject parent) {
this.parent = parent;
}
// pure delegation follows
@Override
public JsObject getProperty(String name) {
return delegate.getProperty(name);
}
@Override
public Collection<? extends DeclarationScope> getChildrenScopes() {
return delegate.getChildrenScopes();
}
@Override
public void addDeclaredScope(DeclarationScope scope) {
delegate.addDeclaredScope(scope);
}
@Override
public Collection<? extends JsObject> getParameters() {
return delegate.getParameters();
}
@Override
public JsObject getParameter(String name) {
return delegate.getParameter(name);
}
@Override
public void addReturnType(TypeUsage type) {
delegate.addReturnType(type);
}
@Override
public Collection<? extends TypeUsage> getReturnTypes() {
return delegate.getReturnTypes();
}
@Override
public Identifier getDeclarationName() {
return delegate.getDeclarationName();
}
@Override
public Map<String, ? extends JsObject> getProperties() {
return delegate.getProperties();
}
@Override
public void addProperty(String name, JsObject property) {
delegate.addProperty(name, property);
}
@Override
public List<Occurrence> getOccurrences() {
return delegate.getOccurrences();
}
@Override
public void addOccurrence(OffsetRange offsetRange) {
delegate.addOccurrence(offsetRange);
}
@Override
public String getFullyQualifiedName() {
return delegate.getFullyQualifiedName();
}
@Override
public Collection<? extends TypeUsage> getAssignmentForOffset(int offset) {
return delegate.getAssignmentForOffset(offset);
}
@Override
public Collection<? extends TypeUsage> getAssignments() {
return delegate.getAssignments();
}
@Override
public int getAssignmentCount() {
return delegate.getAssignmentCount();
}
@Override
public void addAssignment(TypeUsage typeName, int offset) {
delegate.addAssignment(typeName, offset);
}
@Override
public void clearAssignments() {
delegate.clearAssignments();
}
@Override
public boolean isAnonymous() {
return delegate.isAnonymous();
}
@Override
public void setAnonymous(boolean value) {
delegate.setAnonymous(value);
}
@Override
public boolean isDeprecated() {
return delegate.isDeprecated();
}
@Override
public boolean hasExactName() {
return delegate.hasExactName();
}
@Override
public Documentation getDocumentation() {
return delegate.getDocumentation();
}
@Override
public void setDocumentation(Documentation documentation) {
delegate.setDocumentation(documentation);
}
@Override
public int getOffset() {
return delegate.getOffset();
}
@Override
public OffsetRange getOffsetRange() {
return delegate.getOffsetRange();
}
@Override
public JsElement.Kind getJSKind() {
return delegate.getJSKind();
}
@Override
public boolean isDeclared() {
return delegate.isDeclared();
}
@Override
public String getSourceLabel() {
return delegate.getSourceLabel();
}
@Override
public boolean isPlatform() {
return delegate.isPlatform();
}
@Override
public FileObject getFileObject() {
return delegate.getFileObject();
}
@Override
public String getMimeType() {
return delegate.getMimeType();
}
@Override
public String getName() {
return delegate.getName();
}
@Override
public String getIn() {
return delegate.getIn();
}
@Override
public ElementKind getKind() {
return delegate.getKind();
}
@Override
public Set<Modifier> getModifiers() {
return delegate.getModifiers();
}
@Override
public boolean signatureEquals(ElementHandle handle) {
return delegate.signatureEquals(handle);
}
@Override
public OffsetRange getOffsetRange(ParserResult result) {
return delegate.getOffsetRange(result);
}
@Override
public boolean containsOffset(int offset) {
return delegate.containsOffset(offset);
}
@Override
public boolean isVirtual() {
return false;
}
@Override
public boolean moveProperty(String name, JsObject newParent) {
return delegate.moveProperty(name, newParent);
}
}
}