All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.prorefactor.treeparser.TreeParserRootSymbolScope Maven / Gradle / Ivy

There is a newer version: 2.29.1
Show newest version
/********************************************************************************
 * Copyright (c) 2003-2015 John Green
 * Copyright (c) 2015-2024 Riverside Software
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License, v. 2.0 are satisfied: GNU Lesser General Public License v3.0
 * which is available at https://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * SPDX-License-Identifier: EPL-2.0 OR LGPL-3.0
 ********************************************************************************/
package org.prorefactor.treeparser;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nullable;

import org.prorefactor.core.IConstants;
import org.prorefactor.core.schema.Field;
import org.prorefactor.core.schema.IField;
import org.prorefactor.core.schema.ITable;
import org.prorefactor.core.schema.Table;
import org.prorefactor.proparse.support.IProparseEnvironment;
import org.prorefactor.treeparser.symbols.Dataset;
import org.prorefactor.treeparser.symbols.FieldBuffer;
import org.prorefactor.treeparser.symbols.TableBuffer;
import org.prorefactor.treeparser.symbols.Variable;
import org.sonar.plugins.openedge.api.objects.RCodeTTWrapper;

import com.google.common.base.Strings;

import eu.rssw.pct.elements.IBufferElement;
import eu.rssw.pct.elements.IPropertyElement;
import eu.rssw.pct.elements.ITypeInfo;

/**
 * A ScopeRoot object is created for each compile unit, and it represents the program (topmost) scope. For classes, it
 * is the class scope, but it may also have a super class scope by way of inheritance.
 */
public class TreeParserRootSymbolScope extends TreeParserSymbolScope {
  private final IProparseEnvironment refSession;
  private Map tableMap = new HashMap<>();
  private String className = null;
  private ITypeInfo typeInfo = null;
  private boolean isInterface;
  private boolean abstractClass;
  private boolean serializableClass;
  private boolean finalClass;

  public TreeParserRootSymbolScope(IProparseEnvironment session) {
    super(null);
    this.refSession = session;
  }

  public IProparseEnvironment getRefactorSession() {
    return refSession;
  }

  @Override
  public boolean isRootScope() {
    return true;
  }

  @Override
  public TreeParserSymbolScope getTokenSymbolScope(int tokenIndex) { 
    TreeParserSymbolScope rslt = super.getTokenSymbolScope(tokenIndex);
    return rslt == null ? this : rslt;
  }

  public void addTableDefinitionIfNew(ITable table) {
    String lcName = table.getName().toLowerCase();
    tableMap.computeIfAbsent(lcName, key -> table);
  }

  /**
   * Define a temp or work table.
   * 
   * @param name The name, with mixed case as in DEFINE node.
   * @param type IConstants.ST_TTABLE or IConstants.ST_WTABLE.
   * @return A newly created BufferSymbol for this temp/work table.
   */
  public TableBuffer defineTable(String name, int type, boolean noUndo, boolean undo) {
    Table table = new Table(name, type);
    table.setNoUndo(noUndo);
    table.setUndo(undo);
    tableMap.put(name.toLowerCase(), table);
    // Pass empty string for name for default buffer.
    TableBuffer bufferSymbol = new TableBuffer("", this, table);
    // The default buffer for a temp/work table is not "unnamed" the way
    // that the default buffer for schema tables work. So, the buffer
    // goes into the regular bufferMap, rather than the unnamedBuffers map.
    bufferMap.put(name.toLowerCase(), bufferSymbol);
    return bufferSymbol;
  }

  /** Define a temp or work table field */
  public FieldBuffer defineTableField(String name, TableBuffer buffer) {
    ITable table = buffer.getTable();
    IField field = new Field(name, table);
    return new FieldBuffer(this, buffer, field);
  }

  /**
   * Define a temp or work table field. Does not attach the field to the table. That is expected to be done in a
   * separate step.
   */
  public FieldBuffer defineTableFieldDelayedAttach(String name, TableBuffer buffer) {
    IField field = new Field(name, null);
    return new FieldBuffer(this, buffer, field);
  }

  /**
   * Valid only if the parse unit is a CLASS. Returns null otherwise.
   */
  public String getClassName() {
    return className;
  }

  /**
   * Valid only if the parse unit is a CLASS. Returns null otherwise.
   */
  @Nullable
  public ITypeInfo getTypeInfo() {
    return typeInfo;
  }

  /**
   * @return True is parse unit is a CLASS or INTERFACE
   */
  public boolean isClass() {
    return className != null;
  }

  public void setInterface(boolean isInterface) {
    this.isInterface = isInterface;
  }

  public boolean isInterface() {
    return (className != null) && isInterface;
  }

  public void setAbstractClass(boolean abstractClass) {
    this.abstractClass = abstractClass;
  }

  public boolean isAbstractClass() {
    return abstractClass;
  }

  public void setFinalClass(boolean finalClass) {
    this.finalClass = finalClass;
  }

  public boolean isFinalClass() {
    return finalClass;
  }

  public void setSerializableClass(boolean serializableClass) {
    this.serializableClass = serializableClass;
  }

  public boolean isSerializableClass() {
    return serializableClass;
  }

  public TableBuffer getLocalTableBuffer(ITable table) {
    return bufferMap.get(table.getName().toLowerCase());
  }

  @Override
  public Variable lookupVariable(String name) {
    Variable v = super.lookupVariable(name);
    if (v != null) {
      return v;
    }

    ITypeInfo info = typeInfo;
    while (info != null) {
      IPropertyElement prop = info.getProperty(name);
      if (prop != null) {
        Variable retVal = new Variable(name, this);
        if (prop.getVariable() != null)
          retVal.setDataType(prop.getVariable().getDataType());
        return retVal;
      }
      info = refSession.getTypeInfo(info.getParentTypeName());
    }
    return null;
  }

  @Override
  public Dataset lookupDataset(String name) {
    Dataset ds = super.lookupDataset(name);
    if (ds != null) {
      return ds;
    }

    // TODO Lookup in parent classes
    return null;
  }

  /**
   * Lookup a temp or work table definition in this scope. Unlike most other lookup functions, this one has nothing to
   * do with 4gl semantics, buffers, scopes, etc. This just looks up the raw Table definition for a temp or work table.
   * 
   * @return null if not found
   */
  public ITable lookupTableDefinition(String name) {
    return tableMap.get(name.toLowerCase());
  }

  public Collection getAllTableDefinitions() {
    return tableMap.values();
  }

  @Override
  public TableBuffer lookupBuffer(String name) {
    TableBuffer buff = super.lookupBuffer(name);
    if (buff != null) {
      return buff;
    }

    ITypeInfo info = typeInfo;
    while (info != null) {
      if (info.hasBuffer(name)) {
        IBufferElement elem = info.getBuffer(name);
        ITable tbl = null;
        if (!Strings.isNullOrEmpty(elem.getDatabaseName())) {
          tbl = refSession.getSchema().lookupTable(elem.getDatabaseName(), elem.getTableName());
        } else {
          tbl = lookupTempTable(elem.getTableName()).getTable();
        }
        if (tbl == null) {
          // Defaults to fake temp-table
          tbl = new Table(name, IConstants.ST_TTABLE);
        }
        return new TableBuffer(name, this, tbl);
      }
      info = refSession.getTypeInfo(info.getParentTypeName());
    }
    return null;
  }

  @Override
  public TableBuffer lookupTempTable(String name) {
    TableBuffer buff = super.lookupTempTable(name);
    if (buff != null) {
      return buff;
    }
    ITypeInfo info = typeInfo;
    while (info != null) {
      if (info.hasTempTable(name)) {
        return new TableBuffer(name, this, new RCodeTTWrapper(info.getTempTable(name)));
      }
      info = refSession.getTypeInfo(info.getParentTypeName());
    }
    return null;
  }

  /**
   * Lookup an unqualified temp/work table field name. Does not test for uniqueness. That job is left to the compiler.
   * (In fact, anywhere this is run, the compiler would check that the field name is also unique against schema tables.)
   * Returns null if nothing found.
   */
  protected IField lookupUnqualifiedField(String name) {
    IField field;
    for (ITable table : tableMap.values()) {
      field = table.lookupField(name);
      if (field != null)
        return field;
    }
    return null;
  }

  public void setClassName(String s) {
    className = s;
  }

  public void setTypeInfo(ITypeInfo typeInfo) {
    this.typeInfo = typeInfo;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy