Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

yang tool progress #230

Merged
merged 17 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions yang-lsp/.settings/org.eclipse.buildship.core.prefs
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
arguments=
auto.sync=false
build.scans.enabled=false
connection.arguments=
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.gradle.user.home=null
connection.java.home=null
connection.jvm.arguments=
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=
jvm.arguments=
offline.mode=false
override.workspace.settings=false
project.path=\:
show.console.view=false
show.executions.view=false
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,11 @@ class YangContentProposalProvider extends IdeContentProposalProvider {
val modulePrefix = suffix.getSegment(i)
if (modulePrefix != scopeCtx.moduleName) {
val moduleName = suffix.getSegment(i)
val importPrefix = scopeCtx.importedModules.entrySet.findFirst[value.moduleName == moduleName].
key
name.append(importPrefix).append(":")
val importedByName = scopeCtx.importedModules.entrySet.findFirst[value.moduleName == moduleName]
if(importedByName !== null) {
val importPrefix = importedByName.key
name.append(importPrefix).append(":")
}
}
} else {
name.append(suffix.getSegment(i))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package io.typefox.yang.processor

import io.typefox.yang.processor.ProcessedDataTree.AccessKind
import io.typefox.yang.processor.ProcessedDataTree.ElementData
import io.typefox.yang.processor.ProcessedDataTree.HasStatements
import io.typefox.yang.processor.ProcessedDataTree.ListData
import io.typefox.yang.processor.ProcessedDataTree.ModuleData
import java.util.List
import io.typefox.yang.processor.ProcessedDataTree.ElementKind

class DataTreeSerializer {

def CharSequence serialize(ModuleData moduleData) {
'''
module: «moduleData.simpleName»
«FOR child : moduleData.children?:#[]»
«doSerialize(child, '', needsConnect(child, moduleData.children))»
«ENDFOR»

rpcs:
«FOR rpc : moduleData.rpcs?:#[]»
«doSerialize(rpc, '', needsConnect(rpc, moduleData.rpcs))»
«ENDFOR»
'''
}

dispatch def CharSequence doSerialize(HasStatements ele, String indent, boolean needsConnect) {
'''«indent» unsupported data type!'''
}

dispatch def CharSequence doSerialize(ElementData ele, String indent, boolean needsConnect) {
var accessString = " "
if(ele.getAccessKind() != AccessKind.not_set) {
accessString = ele.getAccessKind().name
}
val prefix = switch (ele.elementKind) {
case Case:
'--:'
default: {
'''«"----".substring(accessString.length)»«!accessString.trim.empty?accessString» '''
}
}
val label = switch (ele.elementKind) {
case Choice,
case Case: '''(«ele.name»)'''
default: {
ele.name
}
}
val keys = if (ele instanceof ListData) {
ele.keys.empty ? null : ''' [«ele.keys.join(', ')»]'''
}

val type = ele.getType
// no idea why this indentation is needed in pyang
val additionalIdent = if(ele.elementKind === ElementKind.Choice && prevSibling(ele)?.elementKind === ElementKind.Container) ' ' else ''
'''
«indent»«additionalIdent»+«prefix»«label»«ele.cardinality?.toString()»«keys»«IF type !== null» «type»«ENDIF»«IF ele.featureConditions !== null» {«ele.featureConditions.join(',')»}?«ENDIF»
«IF ele.children !== null»
«FOR child : ele.children»
«doSerialize(child, indent + (needsConnect?'| ':' '), needsConnect(child, ele.children))»
«ENDFOR»
«ENDIF»
'''
}

private def ElementData prevSibling(ElementData ele) {
val siblings = ele.parent?.children
if(siblings === null) {
return null
}
val eleIdx = siblings.indexOf(ele)
if(eleIdx > 0) {
val prevChild = siblings.get(eleIdx - 1)
if(prevChild instanceof ElementData) {
return prevChild
}
}
}

private def boolean needsConnect(HasStatements ele, List<HasStatements> siblings) {
if (siblings === null || siblings.last === ele) {
return false
}
return true
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.typefox.yang.processor;

import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import io.typefox.yang.processor.ProcessedDataTree.ElementIdentifier;
import io.typefox.yang.yang.Feature;

public class FeatureEvaluationContext {

private Map<String, Boolean> cache = Maps.newHashMap();

private Set<String> include = Sets.newHashSet(), exclude = Sets.newHashSet();

public FeatureEvaluationContext(List<String> includedFeatures, List<String> excludedFeatures) {
include.addAll(includedFeatures);
exclude.addAll(excludedFeatures);
}

public boolean isActive(Feature feature) {
ElementIdentifier featureModule = ProcessorUtility.moduleIdentifier(feature);
var featureQName = featureGlobalQName(featureModule, feature.getName());
if (cache.containsKey(featureQName)) {
return cache.get(featureQName);
}
var active = isActive(featureModule.name + ":", featureQName) && featureIfConditionsActive(feature);
cache.put(featureQName, active);
return active;
}

private boolean featureIfConditionsActive(Feature feature) {
return ProcessorUtility.checkIfFeatures(ProcessorUtility.findIfFeatures(feature), this);
}

private boolean isActive(String modulePrefix, String featureQName) {
// include <module>: means include none of <module> features.
if(include.contains(modulePrefix) && !include.contains(featureQName)) {
// include e.g. 'example-system-ext:' means any of example-system-ext module features should be included
return false;
}
return (include.isEmpty() || include.contains(featureQName)
|| !include.contains(modulePrefix)) // if <module>: not listed in include, all features are enabled
&& (exclude.isEmpty() || !(exclude.contains(featureQName) || exclude.contains(modulePrefix)));
}

private String featureGlobalQName(ElementIdentifier module, String featureName) {
return module.name + ":" + featureName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package io.typefox.yang.processor;

import org.eclipse.xtext.nodemodel.util.NodeModelUtils;

import io.typefox.yang.processor.ProcessedDataTree.ElementIdentifier;
import io.typefox.yang.yang.BinaryOperation;
import io.typefox.yang.yang.Expression;
import io.typefox.yang.yang.Feature;
import io.typefox.yang.yang.FeatureReference;
import io.typefox.yang.yang.UnaryOperation;

public class FeatureExpressions {

public static abstract class FeatureCondition {

abstract boolean evaluate(FeatureEvaluationContext ctx);

public static FeatureCondition create(Expression exp) {
return build(exp);
}

private static FeatureCondition build(Expression exp) {
if (exp instanceof FeatureReference) {
return new IsFeatureCondition((FeatureReference) exp, ProcessorUtility.moduleIdentifier(exp));
} else if (exp instanceof UnaryOperation) {
return new IsFeatureCondition((FeatureReference) exp, true, ProcessorUtility.moduleIdentifier(exp));
} else if (exp instanceof BinaryOperation) {
BinaryOperation bin = (BinaryOperation) exp;
return new BinaryFeatureCondition(build(bin.getLeft()), build(bin.getRight()),
"and".equals(bin.getOperator()));
}
return null;
}
}

public static class IsFeatureCondition extends FeatureCondition {

final private Feature feature;
final private boolean not;
final private ElementIdentifier conditionModule;
final private String text;

public IsFeatureCondition(FeatureReference featureRef, ElementIdentifier conditionModule) {
this(featureRef, false, conditionModule);
}

public IsFeatureCondition(FeatureReference featureRef, boolean not, ElementIdentifier conditionModule) {
this.feature = featureRef.getFeature();
this.text = NodeModelUtils.getTokenText(NodeModelUtils.getNode(featureRef));
this.conditionModule = conditionModule;
this.not = not;
}

@Override
boolean evaluate(FeatureEvaluationContext ctx) {
return not ? !ctx.isActive(feature) : ctx.isActive(feature);
}

private String toStringValue = null;

@Override
public String toString() {
if (toStringValue == null) {
toStringValue = (not ? "!" : "") + this.text;
}
return toStringValue;
}
}

public static class BinaryFeatureCondition extends FeatureCondition {
final private FeatureCondition left, right;
final private boolean isAnd;

/**
* Creates an OR binary condition
*
* @param left
* @param right
*/
public BinaryFeatureCondition(FeatureCondition left, FeatureCondition right) {
this(left, right, false);
}

/**
* @param left
* @param right
* @param isAnd <code>true</code> if it's an AND binary condition. Default is
* <code>false</code>: OR
*/
public BinaryFeatureCondition(FeatureCondition left, FeatureCondition right, boolean isAnd) {
super();
this.left = left;
this.right = right;
this.isAnd = isAnd;
}

@Override
boolean evaluate(FeatureEvaluationContext ctx) {
return isAnd ? left.evaluate(ctx) && right.evaluate(ctx) : left.evaluate(ctx) || right.evaluate(ctx);
}

@Override
public String toString() {
return left.toString() + (isAnd ? " and " : " or ") + right.toString();
}
}
}
Loading